Beenden Sie die Anwendung und rufen Sie die Destruktoren lokaler Objekte auf

8

Ich habe einige Objekte auf dem Stapel in der Hauptfunktion:

%Vor%

Außerdem habe ich eine Funktion, die Fehler in meiner Anwendung verfolgt:

%Vor%

Die Err-Funktion ist definitiv nützlich, wenn ich einen schwerwiegenden Fehler melden muss. Ich protokolliere nur den Fehler und beende die Anwendung - sie kann nach solchen Fehlern nicht wiederhergestellt werden. Das Beenden mit "exit ()" ruft foo und bar-Destruktoren jedoch nicht auf - ein Verhalten, das ich eigentlich erwartet hatte (aber falsch war). "abort ()" hilft auch nicht. Außerdem kann ich Ausnahmen nicht verwenden , um sie in main () abzufangen. Gibt es eine andere Möglichkeit, die Err-Funktion so zu implementieren, dass sie die App beendet und die Stack-Objekte korrekt reinigt? Oder sollte ich meine Fehlerbehandlung irgendwie neu gestalten?

Danke!

ps. Übrigens, kann ich keine WM_QUIT-Nachricht an mein Hauptfenster senden? Ich bin nicht gut mit WinAPI, aber meine App ist reines Win32 und meine Err () - Funktion kann ein Handle zu meinem Hauptfenster bekommen. Wird es funktionieren?

    
SadSido 11.04.2011, 14:03
quelle

5 Antworten

3

Nicht ohne Ausnahmen oder normale Rückkehr von Err bis zum Callstack. Sie müssen den Stapel abwickeln.

    
Logan Capaldo 11.04.2011, 14:09
quelle
2

Es gibt immer noch C's setjmp und longjmp . Es sollte dich zurück nach main bringen, also würde das Programm wie üblich nach Verlassen des Bereichs von main enden, in welchem ​​Fall C ++ 's Destruktor-Mechanismus deine lokalen Objekte in main zerstören wird.

Natürlich ist die Verwendung von longjmp in C ++ aus guten Gründen verpönt. Es überspringt alle anderen Funktionen auf dem Stapel, so dass es wirklich nur für einige Stapelobjekte in main funktioniert.

Es könnte einfacher sein, Ihre Objekte auf dem Heap und delete sie manuell in Err zuzuweisen.

    
Alexander Gessler 11.04.2011 14:12
quelle
1

Es gibt grundsätzlich zwei Methoden, um Fehler in C ++ zu verbreiten: Ausnahmen (die Sie scheinbar willkürlich ausgeschlossen haben) und Rückgabecodes.

Da Sie keine Ausnahmen verwenden können, müssen Sie die Rückkehrcodes von Ihren Funktionen, die möglicherweise fehlschlagen, weiterleiten und sie testen, um zu sehen, ob Sie anhalten und zurück zur Hauptfunktion zurückkehren müssen. Wenn Sie den Stapel nicht so abwickeln, können Sie nicht garantieren, dass Destruktoren korrekt aufgerufen werden.

Bedenken Sie auch, dass Destruktoren tatsächlich in der Lage sein werden, wenn Ihr Programm in einem fatalen Zustand ist? Was ist, wenn der Objektstatus fehlerhaft ist und nicht ordnungsgemäß entfernt werden kann? Anstatt exit aufzurufen, könntest du abort aufrufen, was zumindest einen Kern übrig lassen würde, um das Problem zu diagnostizieren, wenn du in einen schlechten Zustand kommst. Für schwerwiegende Fehler, bei denen Ausnahmen nicht verfügbar sind, ist dies eine vernünftige Wahl.

    
Mark B 11.04.2011 14:24
quelle
0

Ich glaube, Exit wird die Anwendung sofort beenden. Um das erwartete Verhalten zu sehen, müssen foo und bar den Gültigkeitsbereich verlassen. Das bedeutet, dass die Hauptfunktion normalerweise mit einem Rückgabewert enden müsste. Anstatt Exit() aus Ihrer Err-Funktion heraus aufzurufen, müssen Sie einen Weg finden, um zu Ihrer Hauptfunktion zurückzukehren und sie normal mit einem Fehlerwert zurückkehren zu lassen.

    
nathan 11.04.2011 14:07
quelle
0

Ich würde Ihre Fehlerbehandlung neu gestalten. Am einfachsten ist es, wenn Sie das Steuerelement an main zurückgeben und es normal säubern lassen. Ausnahmen bieten diese Funktion durch Abwickeln des Stapels, aber Sie können keine Ausnahmen verwenden. OK das passt. Manchmal können Sie Ausnahmen nicht verwenden.

Anstatt Err zu versuchen, das Programm herunterzufahren, muss Err den Fehler protokollieren und einen Fehlercode zurückgeben. Idealerweise sollte Err sowieso nicht zwei Jobs ausführen, die Sie versuchen wollen: 1) Protokollieren Sie den Fehler, 2) Beenden Sie die Anwendung ordnungsgemäß.

Wenn Ihre Anwendung zufällig Multithread ist, haben Sie möglicherweise einen fehlerfreien easy out. Melden Sie im Fehlerprotokollierungsthread ein "Die" -Ereignis. Lassen Sie den Hauptthread auf dieses Ereignis warten und warten Sie auf weitere Aktionen (oder geben Sie einen Job über QueueUserAPC oder ähnliches ein). Wenn das Ereignis gemeldet wird, schließen Sie die App.

    
John Dibling 11.04.2011 14:59
quelle

Tags und Links