2008-12-15 13 views
9

ich einige Code in einem Projekt gefunden, das so aussieht:Macht es Sinn, Ausnahmen im Haupt (...) zu fangen?

int main(int argc, char *argv[]) 
{ 
    // some stuff 

try { 
    theApp.Run(); 
} catch (std::exception& exc) { 
    cerr << exc.what() << std::endl; 
    exit(EXIT_FAILURE); 
} 
return (EXIT_SUCCESS); 
} 

Ich verstehe nicht, warum die Ausnahmen abgefangen werden. Wenn dies nicht der Fall wäre, würde die Anwendung einfach beendet und die Ausnahme gedruckt.

Sehen Sie einen guten Grund, Ausnahmen zu erfassen?


EDIT: Ich stimme zu, dass es gut ist, den Ausnahmefehler zu drucken. Wäre es jedoch nicht besser, die Ausnahme zu wiederholen? Ich habe das Gefühl, dass wir es hier schlucken ...

+0

Wie kann es verschluckt werden? Der Code gibt die Ausnahmebedingungsnachricht aus und wird dann beendet. Was kannst du noch tun? Wenn Sie die Ausnahme wiederholen, wer würde es sehen? Wo würde es gefangen werden? Dies ist immerhin der Einstiegspunkt des Programms. – jalf

Antwort

15

Wenn eine Ausnahme nicht abgefangen wird, definiert der Standard nicht, ob der Stapel abgewickelt wird. So werden auf einigen Plattformen Destruktoren aufgerufen, und bei anderen wird das Programm sofort beendet. Das Abfangen auf der obersten Ebene stellt sicher, dass Destruktoren immer aufgerufen werden.

Also, wenn Sie nicht unter dem Debugger laufen, ist es wahrscheinlich klug, alles zu fangen: (...) sowie std :: Ausnahme. Dann kann Ihr Anwendungscode selbst bei einer schwerwiegenden Ausnahme mit RAII aufräumen. In vielen Fällen müssen Sie nicht wirklich aufräumen, da das Betriebssystem dies für Sie erledigt. Sie ziehen es jedoch vor, wenn möglich, sauber von Remote-Diensten zu trennen, und möglicherweise befinden sich außerhalb des Prozesses Ressourcen wie Named Pipes/Mutexes, die Sie lieber zerstören als auslecken möchten.

Das Auftauchen der Ausnahme in main scheint mir von begrenztem Nutzen, da Sie bereits den Kontext verloren haben, in dem es ursprünglich geworfen wurde. Ich nehme an, dass das Auffangen einer nicht abgefangenen Ausnahme im Debugger lauter ist, als nur den Fehler in std :: cerr zu protokollieren, also wäre das erneute Abrufen der intelligente Zug, wenn es eine Chance gibt, die Protokollierung zu verpassen.

Wenn der Debugger unerwartete Bedingungen im Debugmodus abfangen soll, die im Freigabemodus eine Ausnahme auslösen, die schließlich zu einem Exit führt, gibt es andere Möglichkeiten, als die Ausnahme nicht abgefangen zu lassen, damit der Debugger sie sieht .Zum Beispiel könnten Sie Assert-Makros verwenden. Natürlich hilft das nicht bei unerwarteten und unvorhersehbaren Bedingungen, wie Hardware-Ausnahmen, wenn Sie SEH auf .NET verwenden.

6

Warum sagen Sie, dass die Ausnahme gedruckt würde? Dies ist nicht das typische Verhalten der C++ - Laufzeit. Im besten Fall können Sie erwarten, dass sein Typ gedruckt wird.

Darüber hinaus hinterlässt dieses Programm einen "Fehler" -Status, während eine Ausnahme einen Abbruch-durch-Abbruch-Status (d. H. Mit einem Signal, das in dem Beendigungscode angegeben ist) verursachen kann.

+0

Sie haben Recht, ich dachte fälschlicherweise, dass die Ausnahme gedruckt werden würde. Das ist nicht der Fall. – Barth

3

Dies ist ein globaler Catch-Block. Es ist üblich, anstelle eines kryptischen Ausnahmeausdrucks eine nette und vom Benutzer verstandene Nachricht ('Interner Fehler') anzuzeigen. Dies kann aus dem spezifischen Codeblock nicht offensichtlich sein, aber es ist im Allgemeinen eine gute Idee.

+0

Es ist nur eine gute Idee, bis zum ersten Mal müssen Sie eine mysteriöse Ausnahme debuggen, die aus der Hölle geworfen wird weiß, wo ... :) – Paulius

+1

dann können wir es nicht drucken und es erneut? – Barth

+0

Ich denke, wir können, aber wenn ich debuggen - ich schaue selten, was gedruckt wird - schaue ich normalerweise auf die Werte im Überwachungsfenster (wenn ich muss). – Paulius

6

Try-Catch in der Hauptfunktion verbirgt die Ausnahme vom Debugger. Ich würde sagen, es ist nicht gut.

Auf der anderen Seite, Kunden werden nicht erwartet, Debugger zu haben, so dass das Abfangen von Ausnahmen ist nett. Es ist also gut.

Persönlich erhalte ich alle Ausnahmen in der Hauptfunktion, wenn ich einen Release-Build mache, und ich mache das nicht, wenn ich eine Debug-Konfiguration erstelle.

0

Werfen Sie einen Blick auf die C++ Bibel, d. H. Stroustrup, er hat ein Beispiel, das auch in Applied C++ - Programmierung wiederholt wird. Die Begründung lautet:

+0

Ja. Aber wie ich in meiner Antwort erwähnt habe - es hilft dem Debugger nicht wirklich. Wenn die Ausnahme nicht abgefangen wird, zeigt der Debugger den genauen Speicherort in der Quelle an, in der die Ausnahme ausgelöst wird. Das macht nur in Release-Builds Sinn. – Paulius

4

Ein einfaches Beispiel für eine Situation, in der der Stapel nicht entspannen: Eine Liste von
Why destructor is not called on exception?

Situationen, in denen Ausnahmen die Anwendung eher zu beenden, verursachen können, als der Stapel zu entspannen.
Why destructor is not called on exception?

Wenn eine Ausnahme nicht auf jeder Ebene gefangen und würde entkommen main(), dann wird die Umsetzung zu nennen erlaubt terminate() eher, dass der Stapel Abwickeln (ja, das mich auch überrascht).

Als Ergebnis erhalte ich immer alle Ausnahmen in main().

int main() 
{ 
    try 
    { 
    } 
    catch(std::exception const& e) 
    { /* LOG */ 
     // optimally rethrow 
    } 
    catch(...) // Catch anything else. 
    { /* LOG */ 
     // optimally rethrow 
    } 
} 

Um beim Auffangen von Problemen während des Debuggens zu helfen. Leiten Sie Ihre Ausnahmen von std :: exception ab und hängen Sie den Haltepunkt im Konstruktor für std :: exception fest.

0

Gemäß der Windows-Spezifikation darf die main nicht geworfen werden. (praktisch ergibt es die Nachricht, die fragt, ob Sie den Fehlerbericht an Microsoft senden möchten)

+1

Könnten Sie möglicherweise mit der Windows-Spezifikation verknüpfen, wo dies steht? Das würde Ihrer Antwort einen zusätzlichen Kontext/Autorität geben. – jadarnel27