Was ist besser zu verwenden, ein __try/__except-Block oder ein try/catch-Block?

Lesezeit: 5 Minuten

Benutzer-Avatar
Zain Rizvi

Ich frage mich, was der bessere Weg ist, um Ausnahmen abzufangen, die ich auslöse: Ist es ein __try / __except-Block oder ein try / catch-Block?

Ich schreibe in C++ und das Programm wird nur unter Windows verwendet, daher ist Portabilität kein Problem.

Vielen Dank!

Benutzer-Avatar
Hans Passanten

Sie sind zwei sehr verschiedene Dinge. try/catch sind die vertrauten C++-Schlüsselwörter, die Sie kennen. __try/__except wird verwendet, um SEH-Ausnahmen abzufangen. Von Windows selbst ausgelöste Ausnahmen wie DivisionByZero oder AccessViolation. Es ist gut beschrieben in der Artikel der MSDN-Bibliothek dafür.

Sie können es auch verwenden, um eine C++-Ausnahme abzufangen, da es die Windows SEH-Funktion nutzt. Sie können das ausgelöste Ausnahmeobjekt jedoch nicht herausholen, sodass es keinen Kontext gibt, wenn Sie tatsächlich möchten, dass die Ausnahme behandelt wird. Was Wahnsinn ist. Der wichtigste Ansatz besteht darin, SEH-Ausnahmen niemals abzufangen, sie sind immer grob. Wenn Sie die beiden heiraten müssen, verwenden Sie _set_se_translator(), um die SEH-Ausnahme in eine C++-Ausnahme umzuwandeln.

Benutzer-Avatar
Billy ONeal

Sie sollten eine verwenden try/catch Block.

Wie andere schon geantwortet haben, __try / __except dient zum Abfangen von SEH (von Windows generierte Fehler), nicht zum Abfangen allgemeiner Ausnahmen.

Am wichtigsten, __try und __catch führt möglicherweise keine C++-Destruktoren aus oder entlädt den Stapel nicht korrekt, wenn eine Ausnahme ausgelöst wird.

Außer in seltenen Fällen sollten Sie niemals versuchen, SEH-Ausnahmen abzufangen.

BEARBEITEN: Nun, ich war diesbezüglich positiv (das wurde mir immer gesagt), aber @Hans sagt, dass es anscheinend einen Compiler-Schalter gibt, mit dem Sie dies ändern können. Ich denke, die Dokumente auf /EHa sind irreführend oder zumindest unvollständig darüber, was hier passiert. Wenn jemand endgültige Dokumente findet, die dies als falsch beweisen, werde ich diese Antwort gerne entfernen.

Auch wenn sich herausstellt, dass dies falsch ist, sollten Sie es trotzdem verwenden try und catch einfach weil sie Standard sind, während __try und __except sind nicht.

  • @David: Das ist richtig. __try und __except sind ausschließlich eine C-basierte API/ABI.

    – Billy ONeal

    16. September 2010 um 21:15 Uhr

  • Das ist nicht genau. Das Kompilieren mit /EHa garantiert C++-Destruktoraufrufe während des Stack-Unwinding.

    – Hans Passant

    17. September 2010 um 9:12 Uhr

  • @Hans: Kannst du dazu eine Dokumentation finden? Mein Verständnis von /EHa ist lediglich, dass es Konstrukte zur Ausnahmebehandlung in C++ zulässt (wenn Sie try und catch), um SEH-Ausnahmen abzufangen, aber dass der C++-Stack immer noch nicht korrekt entladen wird, wenn __try und __except werden verwendet.

    – Billy ONeal

    17. September 2010 um 14:38 Uhr

  • Die /EH-Dokumentation ist alles, was es gibt. Ja, es ist nicht toll. /EHa unterdrückt eine Compileroptimierung, die Ausnahmebereinigungshandler auslässt, wenn der Compiler erkennt, dass keiner der ausgegebenen Codes eine C++-Ausnahme auslösen kann. Sie können sie sehen, wenn Sie sich den Maschinencode ansehen.

    – Hans Passant

    17. September 2010 um 14:45 Uhr

  • @Alex: __except kann C++-Ausnahmen abfangen; Mein Verständnis ist jedoch, dass es nicht garantiert ist, dass dabei C++-Stack-Unwind-Semantik bereitgestellt wird. Außer, wie Hans behauptet, unter /EHa. (Bitte bitte bitte nicht verwenden /EHa)

    – Billy ONeal

    19. März 2014 um 3:28 Uhr

__try/__except ist für den Aufruf von Win32-C-Code konzipiert, der keine Ausnahmen unterstützt, aber einen strukturierten Fehlercode / Behandlungsmechanismus verwendet. __try/__except übersetzt C-Fehler in einen Ausnahmeblock ähnlich zu C++ try/catch.

Weitere Informationen finden Sie unter diesen MSDN-Artikel.

Benutzer-Avatar
Cătălin Pitiș

Standard-C++ verwendet Try/Catch-Blöcke, daher würde ich empfehlen, sie zu verwenden, wenn Sie den “Standard”-Ausnahmemechanismus benötigen, der auf der Standard-C++-Bibliothek basiert.

Wenn Sie jedoch die strukturierte Ausnahmebehandlung verwenden möchten, die über das Windows SDK bereitgestellt wird (siehe hier), dann benutze __try/__except.

Sobald Sie etwas geworfen haben, haben Sie keine große Wahl mehr, wie Sie es fangen können. Wenn Sie C++-Ausnahmen auslösen (z. B. with throw), dann benutze try/catch. Wenn Sie Windows-Ausnahmen auslösen (z. B. with RaiseException), dann benutze __try/__except. Der Versuch, sie zu mischen, fügt Ihrem Leben nur unnötigen Ärger hinzu.

  • Aber Sie sollten niemals Windows-Ausnahmen auslösen, da sie den Stack nicht abwickeln.

    – Billy ONeal

    16. September 2010 um 21:27 Uhr

  • @BillyONeal ist anscheinend die einzige Möglichkeit, einen Threadnamen vor Windows10 festzulegen: docs.microsoft.com/en-us/visualstudio/debugger/…

    – chacham15

    20. Mai 2020 um 16:14 Uhr

  • Das Entladen des Stapels ist in diesem Fall irrelevant, @chacham, da Sie nur werfen, um die Aufmerksamkeit des Debuggers zu erregen, und nicht, um den Programmablauf zu ändern. Sie fangen die Ausnahme sofort ab und verwerfen sie. Der Punkt bleibt jedoch, dass Sie keine wirkliche Wahl haben wie Sie fangen diese Ausnahme ab. Du wirfst es mit RaiseExceptionalso musst du es mit fangen __except.

    – Rob Kennedy

    21. Mai 2020 um 20:31 Uhr

  • Sicher, aber “Aber Sie sollten niemals Windows-Ausnahmen auslösen” ist nicht ganz richtig.

    – chacham15

    22. Mai 2020 um 20:30 Uhr

  • Aber Sie sollten niemals Windows-Ausnahmen auslösen, da sie den Stack nicht abwickeln.

    – Billy ONeal

    16. September 2010 um 21:27 Uhr

  • @BillyONeal ist anscheinend die einzige Möglichkeit, einen Threadnamen vor Windows10 festzulegen: docs.microsoft.com/en-us/visualstudio/debugger/…

    – chacham15

    20. Mai 2020 um 16:14 Uhr

  • Das Entladen des Stapels ist in diesem Fall irrelevant, @chacham, da Sie nur werfen, um die Aufmerksamkeit des Debuggers zu erregen, und nicht, um den Programmablauf zu ändern. Sie fangen die Ausnahme sofort ab und verwerfen sie. Der Punkt bleibt jedoch, dass Sie keine wirkliche Wahl haben wie Sie fangen diese Ausnahme ab. Du wirfst es mit RaiseExceptionalso musst du es mit fangen __except.

    – Rob Kennedy

    21. Mai 2020 um 20:31 Uhr

  • Sicher, aber “Aber Sie sollten niemals Windows-Ausnahmen auslösen” ist nicht ganz richtig.

    – chacham15

    22. Mai 2020 um 20:30 Uhr

1375220cookie-checkWas ist besser zu verwenden, ein __try/__except-Block oder ein try/catch-Block?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy