Ich lese über Ausnahmebehandlung. Ich habe einige Informationen zur Ausnahmebehandlung erhalten, habe aber einige Fragen:
- Wann eine Ausnahme auslösen?
- Können wir anstelle einer Ausnahme einen Rückgabewert verwenden, um den Fehler anzuzeigen?
- Wenn ich alle meine Funktionen durch Try-Catch-Blöcke schütze, verringert dies nicht die Leistung?
- Wann wird die Ausnahmebehandlung verwendet?
- Ich habe ein Projekt gesehen, in dem jede Funktion in diesem Projekt einen Try-Catch-Block enthielt (dh Code innerhalb der gesamten Funktion ist von einem Try-Catch-Block umgeben). Ist das eine gute Praxis?
- Was ist der Unterschied zwischen try-catch und __try __except?
c++
windows
exception
exception-handling
Umesha MS
quelle
quelle
Antworten:
Hier ist eine ziemlich umfassende Anleitung zu Ausnahmen, die ich für ein Muss halte:
Ausnahmen und Fehlerbehandlung - C ++ FAQ oder C ++ FAQ lite
Als Faustregel gilt, dass Sie eine Ausnahme auslösen müssen, wenn Ihr Programm eine externe Person identifizieren kannProblem, das die Ausführung verhindert. Wenn Sie Daten vom Server empfangen und diese Daten ungültig sind, lösen Sie eine Ausnahme aus. Nicht genügend Speicherplatz? Eine Ausnahme auslösen. Kosmische Strahlung hindert Sie daran, die Datenbank abzufragen? Eine Ausnahme auslösen. Wenn Sie jedoch ungültige Daten aus Ihrem eigenen Programm erhalten, lösen Sie keine Ausnahme aus. Wenn Ihr Problem von Ihrem eigenen schlechten Code herrührt, ist es besser, ASSERTs zu verwenden, um sich dagegen zu schützen. Die Ausnahmebehandlung ist erforderlich, um Probleme zu identifizieren, die das Programm nicht behandeln kann, und um sie über den Benutzer zu informieren, da der Benutzer sie behandeln kann. Aber Fehler in Ihrem Programm können vom Benutzer nicht behandelt werden, sodass ein Programmabsturz nicht viel weniger aussagt als "Der Wert von answer_to_life_and_universe_and_everything ist nicht 42! Dies sollte niemals passieren !!!! 11" Ausnahme.
Fangen Sie eine Ausnahme ab, in der Sie etwas Nützliches tun können, z. B. ein Meldungsfeld anzeigen. Ich ziehe es vor, eine Ausnahme einmal in einer Funktion abzufangen, die irgendwie Benutzereingaben verarbeitet. Zum Beispiel drückt der Benutzer die Taste "Alle Hunams vernichten" und in der Funktion "AnnihilateAllHunamsClicked ()" gibt es einen try ... catch-Block, um "Ich kann nicht" zu sagen. Obwohl die Vernichtung von hunamkind eine komplexe Operation ist, bei der Dutzende und Dutzende von Funktionen aufgerufen werden müssen, gibt es nur einen Versuch ... catch, denn für einen Benutzer ist es eine atomare Operation - ein Knopfdruck. Ausnahmeprüfungen in jeder Funktion sind redundant und hässlich.
Außerdem kann ich nicht genug empfehlen, sich mit RAII vertraut zu machen - das heißt, um sicherzustellen, dass alle initialisierten Daten automatisch zerstört werden. Dies kann erreicht werden, indem so viel wie möglich auf dem Stapel initialisiert wird. Wenn Sie etwas auf dem Heap initialisieren müssen, verwenden Sie eine Art intelligenten Zeiger. Alles, was auf dem Stapel initialisiert wurde, wird automatisch zerstört, wenn eine Ausnahme ausgelöst wird. Wenn Sie dumme Zeiger im C-Stil verwenden, besteht die Gefahr eines Speicherverlusts, wenn eine Ausnahme ausgelöst wird, da niemand sie bei einer Ausnahme bereinigen kann (Sie können Zeiger im C-Stil als Mitglieder Ihrer Klasse verwenden, stellen Sie jedoch sicher, dass dies der Fall ist im Destruktor erledigt).
quelle
fclose
dann lieber nicht !). Sie erhalten keine vollständige Stapelverfolgung.Ausnahmen sind unter verschiedenen Umständen nützlich.
Erstens gibt es einige Funktionen, bei denen die Kosten für die Berechnung der Vorbedingung so hoch sind, dass es besser ist, nur die Berechnung durchzuführen und mit einer Ausnahme abzubrechen, wenn festgestellt wird, dass die Vorbedingung nicht erfüllt ist. Zum Beispiel können Sie eine singuläre Matrix nicht invertieren. Um jedoch zu berechnen, ob sie singulär ist, berechnen Sie die Determinante, die sehr teuer ist: Möglicherweise muss sie ohnehin innerhalb der Funktion durchgeführt werden. Versuchen Sie also einfach, die Matrix und den Bericht zu invertieren Ein Fehler, wenn Sie keine Ausnahme auslösen können. Dies ist grundsätzlich eine Ausnahme als negative Vorbedingung .
Dann gibt es andere Fälle, in denen Ihr Code bereits komplex ist und es schwierig ist, Fehlerinformationen über die Aufrufkette zu übertragen. Dies liegt zum Teil daran, dass C und C ++ fehlerhafte Datenstrukturmodelle haben: Es gibt andere, bessere Möglichkeiten, aber C ++ unterstützt sie nicht (z. B. die Verwendung von Monaden in Haskell). Diese Verwendung ist im Grunde genommen nicht die Mühe, es richtig zu machen, also werde ich eine Ausnahme werfen : Es ist nicht der richtige Weg, aber es ist praktisch.
Dann gibt es die Hauptverwendung von Ausnahmen: um zu melden, wenn externe Voraussetzungen oder Invarianten, wie z. B. ausreichende Ressourcen wie Speicher oder Speicherplatz, nicht verfügbar sind. In diesem Fall beenden Sie normalerweise das Programm oder einen wichtigen Unterabschnitt davon. Die Ausnahme ist eine gute Möglichkeit, Informationen über das Problem zu übertragen. C ++ - Ausnahmen wurden entwickelt, um Fehler zu melden, die verhindern, dass das Programm fortgesetzt wird .
Es ist bekannt , dass das in den meisten modernen Sprachen, einschließlich C ++, verwendete Ausnahmebehandlungsmodell fehlerhaft ist . Es ist viel zu mächtig. Theoretiker haben jetzt bessere Modelle entwickelt als das völlig offene Modell "Alles werfen" und "Vielleicht und vielleicht nicht fangen". Darüber hinaus war es keine gute Idee, Typinformationen zur Klassifizierung von Ausnahmen zu verwenden.
Das Beste, was Sie tun können, ist , Ausnahmen sparsam zu werfen, wenn ein tatsächlicher Fehler vorliegt und wenn es keine andere Möglichkeit gibt, damit umzugehen und Ausnahmen so nahe wie möglich am Wurfpunkt zu fangen .
quelle
Ich bin mit diesem Aspekt der akzeptierten Antwort nicht einverstanden . Eine Behauptung ist zweifellos nicht besser als eine Ausnahme auszulösen. Wenn Ausnahmen nur für Laufzeitfehler (oder "externe Probleme") geeignet waren, wozu
std::logic_error
?Ein logischer Fehler ist fast per Definition die Art von Bedingung, die verhindert, dass ein Programm fortgesetzt wird. Wie kann das Programm fortgesetzt werden, wenn es sich um ein logisches Konstrukt handelt und eine Bedingung außerhalb des Bereichs dieser Logik auftritt? Sammeln Sie Eingaben, solange Sie können, und werfen Sie eine Ausnahme!
Es ist nicht so, dass es keinen Stand der Technik gibt.
std::vector
, um nur einen zu nennen, löst eine logische Fehlerausnahme aus, nämlichstd::out_of_range
. Wenn Sie die Standard - Bibliothek verwenden und haben keine Top-Level - Handler Standard Ausnahmen zu fangen - wenn auch nur zu nennen , was () und Ausgang (3) - dann Ihre Programme unterliegen einer abrupte stille, Kündigung.Ein Assert-Makro ist eine viel schwächere Wache. Es gibt keine Wiederherstellung. Es sei denn, Sie führen keinen Debug-Build aus. In diesem Fall erfolgt keine Ausführung . Das Assert-Makro gehört zu einer Zeit, in der die Berechnung um 6 Größenordnungen langsamer war als heute. Wenn Sie sich die Mühe machen, auf Logikfehler zu testen, diesen Test jedoch nicht verwenden, wenn es darauf ankommt, sollten Sie in der Produktion viel Vertrauen in Ihren Code haben!
Die Standardbibliothek sieht logische Fehlerausnahmen vor und verwendet diese. Sie sind aus einem Grund da: weil logische Fehler auftreten und außergewöhnlich sind. Nur weil C Assertions enthält, ist dies kein Grund, sich auf einen solchen primitiven (und wohl nutzlosen) Mechanismus zu verlassen, wenn eine Ausnahme den Job so viel besser erledigt.
quelle
Am besten dafür lesen
In den letzten anderthalb Jahrzehnten wurde viel über die Behandlung von Ausnahmen gesprochen. Trotz eines allgemeinen Konsenses darüber, wie Ausnahmen richtig behandelt werden sollen, besteht weiterhin eine Kluft bei der Nutzung. Eine unsachgemäße Ausnahmebehandlung ist leicht zu erkennen, leicht zu vermeiden und eine einfache Qualitätsmetrik für Code (und Entwickler). Ich weiß, dass absolute Regeln engstirnig oder übertrieben wirken, aber generell sollten Sie try / catch nicht verwenden
http://codebetter.com/karlseguin/2010/01/25/don-t-use-try-catch/
quelle
try
/ nichtcatch {}
?1. Eine Ausnahmeprüfung ist im Code enthalten, wenn die Möglichkeit besteht, dass eine Ausnahme als Ergebnis oder irgendwo zwischen dem Problem auftritt.
2.Verwenden Sie den Try-Catch-Block nur in den Fällen, in denen dies erforderlich ist. Die Verwendung jedes Try-Catch-Blocks trägt zu einer zusätzlichen Bedingungsprüfung bei, die die Optimierung des Codes sicherlich verringert.
3.Ich denke, _try_except ist ein gültiger Variablenname ....
quelle
Der grundlegende Unterschied ist:
eine ist, dass du deine eigenen machst.
Zum Beispiel könnten Sie einen Ausdruck machen
0 divide error
. Die Verwendung von try catch1.
hilft Ihnen, wenn ein Fehler aufgetreten ist. Oder du brauchst einif a==0 then..
in2.
Wenn Sie nicht versuchen, die Ausnahme abzufangen, denke ich nicht, dass sie schneller ist, sondern nur umgeht. Wenn sie
error
auftritt, handelt es sichthrew
um einen externen Handler.Sich selbst zu übergeben bedeutet, dass das Problem in vielen Fällen nicht weiter geht und dann einen Geschwindigkeitsvorteil hat, aber nicht immer.
Vorschlag: Behandeln Sie sich einfach, wenn es einfach und logisch ist.
quelle
Viele C / C ++ - Puristen raten von Ausnahmen ab. Die Hauptkritikpunkte sind:
Überprüfen Sie stattdessen bei jedem Aufruf einer Funktion den Rückgabewert / Fehlercode.
quelle