Domanda

Questa domanda fornisce maggiore chiarezza sul problema descritto qui . Ho fatto qualche indagine in più e ho scoperto che lo svolgersi dello stack non sta avvenendo nel seguente pezzo di codice:

class One
{
public:
    int x ;
};

class Wrapper
{
public:
    Wrapper(CString csText):mcsText(csText)
    {
        CString csTempText;
        csTempText.Format("Wrapper constructor :: %s\n", mcsText);
        OutputDebugString(csTempText);
    }

    ~Wrapper()
    {
        CString csTempText;
        csTempText.Format("Wrapper destructor :: %s\n", mcsText);
        OutputDebugString(csTempText);
    }
    CString mcsText;
};
class Test
{
    public:

    void notifyError()
    {
        try
        {
            int x = 10; 
        }
        catch(...)  {}
    }

    void OnRecvBuffer()
    {
        try
        {
            Wrapper a("AddRef");    
            One* p = NULL;
            p->x = 10;
        }
        catch(...)
        {
            notifyError();
        }   
    }   
};



int main() 
{
    Test* pTest = new Test;

    pTest->OnRecvBuffer();

    OutputDebugString("Test");
}

Ho compilato questo codice usando il compilatore VC6 SP5 e l'output è " Costruttore di wrapper :: AddRef !!! " (ovvero il distruttore dell'oggetto wrapper che è stato costruito sullo stack non viene chiamato. È questo il comportamento previsto? O è un bug con il compilatore VC? Posso usare alcuni flag del compilatore in modo che lo svolgersi dello stack avvenga in questo caso?

È stato utile?

Soluzione

Se si desidera utilizzare SEH, è necessario utilizzare la funzione _set_se_translator e l'opzione del compilatore / EHa.

Altri suggerimenti

Lo standard C ++ non fornisce nulla su cui lavorare in caso di comportamento indefinito. Anche se lo fa la SM. Questa è una cosa specifica della piattaforma, quindi attenzione. Alcune di queste eccezioni in virgola mobile vengono trasformate in eccezioni Win32 che è possibile tentare di rilevare con _set_se_translator () . Il problema è che puoi rilevare le eccezioni di Win32 ma il tuo stack non verrà srotolato correttamente. Almeno questo non è qualcosa su cui puoi scommettere la tua vita. In che consiste l'inutilità dell'esercizio.

  

Aggiornamento: l'eccezione viene generata intenzionalmente per controllare lo svolgimento dello stack. La domanda è: perché il distruttore della classe Wrapper non viene chiamato. - Naveen

In questo caso, non farlo. Esistono modi migliori per generare eccezioni rispetto a Undefined Behaviour.

per esempio:

void OnRecvBuffer()
{
    try
    {
        Wrapper a("AddRef");    
        throw 42; // this'll throw an exception without invoking UB
    }
    catch(...)
    {
        notifyError();
    }
}

Non è possibile dereferenziare un puntatore NULL. Stai invocando Undefined Behaviour qui:

One* p = NULL;
p->x = 10;

Dopo quella linea tutte le scommesse sono spente e potresti averci ucciso tutti;)

p è un puntatore a un oggetto One . Dovrebbe contenere l'indirizzo di un oggetto One . Lo hai inizializzato su 0 - non esiste alcun oggetto all'indirizzo 0. 0 non è un indirizzo valido per nessun oggetto (questo è garantito dallo standard).

Poiché l'eccezione regolare C ++ non gestisce questo tipo di eccezione, è necessario utilizzare SEH che non conosce nulla sull'app e non si svolge.

Questo è un comportamento indefinito:

One* p = NULL;
p->x = 10;

A questo punto l'applicazione è libera di bloccarsi senza srotolare lo stack.
Se si desidera testare lo svolgimento dello stack, sostituirlo con:

 throw 42; // Life the Universe and Everything thrown away

Non dovresti allocare dinamicamente tutti i tuoi oggetti, questo è C ++ non Java!

int main() 
{
    Test    pTest;   // Note the lack of new!

    pTest.OnRecvBuffer();

    OutputDebugString("Test");
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top