Frage

Diese Frage stellt mehr Klarheit über das Problem beschrieben hier . Ich habe einige weitere Untersuchung und stellte fest, dass der Stapel Abwickeln geschieht nicht in dem folgenden Code:

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");
}

ich diesen Code mit VC6 SP5-Compiler kompiliert und der Ausgang ist "Wrapper Konstruktor :: AddRef !!!" (Dh die destructor von Wrapper-Objekt, das auf Stapel aufgebaut wurde, wird nicht genannt. Ist dies das erwartete Verhalten? Oder ist es ein Fehler mit VC-Compiler? Kann ich einige Compiler-Flags verwenden, so dass der Stapel Abwickeln in diesem Fall passiert?

War es hilfreich?

Lösung

Wenn Sie SEH verwenden möchten, müssen Sie _set_se_translator Funktion und / EHa Compiler-Option verwenden.

Andere Tipps

Der C ++ Standard gibt nichts mit undefiniertem Verhalten bei arbeiten. Auch wenn MS der Fall ist. Das ist eine Plattform-spezifische Sache - also Vorsicht. Einige solche Gleitkomma Ausnahmen sind Win32 Ausnahmen eingeschaltet, die Sie versuchen können, mit _set_se_translator() zu fangen. Das Problem ist, dass Sie Win32 Ausnahmen abfangen können, aber dann Stapel nicht ordnungsgemäß abgewickelt werden. Zumindest das ist nicht etwas, das Sie Ihr Leben auf wetten. Worin liegt die Nutzlosigkeit der Übung.

  

Update: Die Ausnahme ausgelöst wird absichtlich den Stapel Abwickeln zu überprüfen. Die Frage ist, warum destructor die Wrapper-Klasse wird nicht genannt zu werden. - Naveen

Wenn dies der Fall ist - tun Sie es nicht. Es gibt bessere Möglichkeiten Ausnahmen zu werfen als über nicht definiertes Verhalten.

Z. B:

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

Sie können nicht dereferenzieren einen NULL-Zeiger. Sie berufen sich nicht definiertes Verhalten hier:

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

Nach dieser Zeile sind alle Wetten ab, und Sie konnte getötet haben uns alle;)

p ist ein Zeiger auf ein Objekt One. Es sollte die Adresse eines One Objekt enthält. Sie haben es auf 0 initialisiert - es gibt kein Objekt mit der Adresse 0. 0 ist keine gültige Adresse für jedes Objekt (das von der Norm guranteed wird)

.

Da C ++ regelmäßige Ausnahme diese Art von Ausnahme nicht verarbeitet, müssen Sie SEH verwenden, die nicht weiß nichts über die App und entspannen Sie sich nicht.

Dies ist nicht definiertes Verhalten:

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

An diesem Punkt ist die Anwendung frei ohne Abwickeln des Stapels zum Absturz bringen.
Wenn Sie möchten, um den Stapel testen Abwickeln ersetzen diese mit:

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

Sie sollten nicht dynamisch alle objcts zuteilen dies ist C ++ Java nicht!

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

    pTest.OnRecvBuffer();

    OutputDebugString("Test");
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top