Unterschied zwischen der Verwendung des try-Catch-Exception-Handlers und der if-Bedingungsprüfung? [Duplikat]

8

Ich habe an vielen Stellen schon andere Anweisungen verwendet, allerdings bin ich neu in der Ausnahmebehandlung. Was ist der Hauptunterschied zwischen diesen beiden ...

für zB:

%Vor%

ODER

%Vor%

Also verwenden wir hier Standardklasse für Ausnahme, die einige in build Funktion wie e.what hat. Es kann also ein Vorteil sein ... abgesehen davon, dass wir alle anderen Funktionen handhaben können, wenn auch sonst. Gibt es noch andere Vorteile bei der Verwendung der Ausnahmebehandlung?

danke

    
Newbee 19.08.2013, 06:37
quelle

5 Antworten

2

Um zu sammeln, was die Kommentare in einer Antwort sagen:

seit der Standardisierung 1998 gibt new bei einem Fehler keinen Nullzeiger zurück, sondern löst eine Ausnahme aus, nämlich std::bad_alloc . Dies unterscheidet sich von Cs malloc und vielleicht von einigen frühen Vor-Standard-Implementierungen von C ++, wobei new möglicherweise auch NULL zurückgegeben hat (ich weiß nicht, tbh).

Es gibt eine Möglichkeit in C ++, einen Nullzeiger bei einem Zuteilungsfehler anstatt einer Ausnahme zu erhalten:

%Vor%

Kurz gesagt, der erste Code, den Sie haben, wird nicht wie beabsichtigt funktionieren, da es ein Versuch der C-style-Fehlerbehandlung in Gegenwart von C ++ - Ausnahmen ist. Wenn die Zuweisung fehlschlägt, wird die Ausnahme ausgelöst, der if-Block wird nie eingegeben und das Programm wird wahrscheinlich beendet, da Sie bad_alloc nicht abfangen.

Es gibt viele Artikel, in denen die allgemeine Fehlerbehandlung mit Ausnahmen verglichen mit Rückgabecodes verglichen wird, und es würde viel zu weit gehen, um das Thema hier zu behandeln. Zu den Gründen für Ausnahmen gehören

  • Funktionsrückgabetypen sind nicht von der Fehlerbehandlung betroffen, können aber echte Werte zurückgeben - es sind keine Funktionsparameter für die Ausgabe erforderlich.
  • Sie müssen nicht die Rückgabe jedes einzelnen Funktionsaufrufs in jeder einzelnen Funktion behandeln, sondern können die Ausnahme nur einige Ebenen in der Aufrufliste abfangen, wo Sie tatsächlich den Fehler
  • verarbeiten können
  • Ausnahmen können Arbitrationsinformationen an die Fehlerbehandlungssite übergeben, verglichen mit einer globalen errno -Variable und einem einzelnen zurückgegebenen Fehlercode.
Arne Mertz 19.08.2013, 06:50
quelle
2

Der Hauptunterschied besteht darin, dass die Version, die mindestens die Ausnahmebehandlung verwendet, funktionieren könnte, wobei die mit der if -Anweisung möglicherweise nicht funktionieren kann.

Dein erstes Snippet:

%Vor%

... scheint davon auszugehen, dass new im Falle eines Fehlers einen Nullzeiger zurückgibt. Während das zu einer Zeit wahr war, war es nicht in einer langen Zeit. Mit jedem einigermaßen aktuellen Compiler hat das new nur zwei Möglichkeiten: Erfolg oder Wurf. Daher stimmt Ihre zweite Version damit überein, wie C ++ funktionieren soll.

Wenn Sie wirklich diesen Stil verwenden möchten, können Sie den Code so umschreiben, dass er im Falle eines Fehlers einen Nullzeiger zurückgibt:

%Vor%

In den meisten Fällen sollten Sie new sowieso nicht direkt verwenden - Sie sollten wirklich std::vector<int> p(1000); verwenden und damit fertig sein.

Damit bin ich gezwungen, hinzuzufügen, dass es für eine Menge Code wahrscheinlich am sinnvollsten ist, beides nicht zu tun und einfach anzunehmen, dass die Speicherzuweisung erfolgreich sein wird.

Zu einer Zeit (MS-DOS) war es ziemlich üblich, dass die Speicherzuweisung fehlschlug, wenn Sie versuchten, mehr Speicher zuzuweisen als verfügbar war - aber das war lange her. Heutzutage sind die Dinge nicht so einfach (in der Regel). Aktuelle Systeme verwenden virtuellen Speicher, was die Situation viel komplizierter macht.

Unter Linux passiert normalerweise, dass selbst der Speicher nicht wirklich verfügbar ist. Linux wird das tun, was als "Overcommit" bezeichnet wird. Sie erhalten immer noch einen Nicht-Null-Zeiger, als ob die Zuweisung erfolgreich gewesen wäre - aber wenn Sie versuchen, den Speicher zu verwenden, werden schlimme Dinge passieren. Insbesondere hat Linux einen sogenannten "OOM-Killer", der im Grunde davon ausgeht, dass das Auslaufen von Arbeitsspeicher ein Zeichen für einen Fehler ist. Wenn dies geschieht, versucht es, die fehlerhaften Programme zu finden und tötet sie. Für den praktischsten Zweck bedeutet dies, dass Ihr Programm wahrscheinlich getötet wird, und andere (halb-willkürlich gewählte) auch sein können.

Windows bleibt dem Modell, das C ++ erwartet, etwas näher. Wenn also beispielsweise Ihr Code auf einem unbeaufsichtigten Server ausgeführt wird, schlägt die Zuweisung möglicherweise fehl. Lange bevor es jedoch scheitert, wird es den Rest der Maschine in die Knie zwingen und in einem verhängnisvollen Versuch, die Zuweisung erfolgreich zu machen, verrückt tauschen. Wenn der Benutzer den Computer zu dem Zeitpunkt tatsächlich betreibt, wird in der Regel entweder Ihr Programm beendet oder andere deaktiviert, um genügend Speicher für Ihren Code freizugeben, um den angeforderten Speicher relativ schnell zu erhalten.

In keinem dieser Fälle ist es besonders realistisch, gegen die Annahme zu programmieren, dass eine Zuteilung fehlschlagen kann. Für die meisten praktischen Zwecke passiert eines von zwei Dingen: Entweder ist die Zuweisung erfolgreich oder das Programm stirbt.

Das führt zurück zum vorherigen Hinweis: In einem typischen Fall sollten Sie in der Regel std::vector verwenden und davon ausgehen, dass Ihre Zuweisung erfolgreich ist . Wenn Sie darüber hinaus Verfügbarkeit bereitstellen müssen, müssen Sie es einfach auf andere Weise tun (z. B. den Prozess neu starten, wenn er abbricht, vorzugsweise auf eine Weise, die weniger Arbeitsspeicher belegt).

    
Jerry Coffin 19.08.2013 07:07
quelle
2

Wie bereits erwähnt, würde Ihr ursprüngliches if-else-Beispiel immer noch eine Ausnahme ab C ++ 98 auslösen, obwohl das Hinzufügen von nothrow (wie bearbeitet) es wie gewünscht funktionieren lassen sollte (return null , also trigg if- Aussage).

Im Folgenden gehe ich vereinfachend davon aus, dass für if-else zur Behandlung von Ausnahmen Funktionen zurückgegeben werden, die bei einer Ausnahme den Wert false zurückgeben.

Einige Vorteile von Ausnahmen oben, wenn-sonst, aus dem Kopf:

  • Sie kennen den Typ der Ausnahme für Logging / Debugging / Bugfixing

    Beispiel:

    Wenn eine Funktion eine Ausnahme auslöst, können Sie in angemessenem Umfang feststellen, ob ein Problem mit dem Code vorliegt oder etwas, das Sie nicht wie eine Ausnahme wegen zu wenig Speicherplatz ausführen können.

    Wenn das if-else eine Funktion zurückgibt, haben Sie keine Ahnung, was in dieser Funktion passiert ist.

    Sie können natürlich eine separate Protokollierung verwenden, um diese Informationen aufzuzeichnen, aber warum nicht einfach eine Ausnahme mit den Ausnahmedetails zurückgeben, die stattdessen enthalten sind?

  • Sie müssen kein Chaos von if-else-Bedingungen haben, um die Ausnahme an die aufrufende Funktion weiterzugeben

    Beispiel: (Kommentare enthalten, um Verhalten anzuzeigen)

    %Vor%

    (Es gibt viele Leute, die nicht gerne Funktionen mit mehreren Return-Anweisungen haben. In diesem Fall haben Sie eine noch unordentlichere Funktion.)

    Im Gegensatz zu:

    %Vor%

Eine Alternative zu oder Erweiterung von if-else sind Fehlercodes. Dafür bleibt der zweite Punkt erhalten. Siehe für mehr über den Vergleich zwischen diesen und Ausnahmen.

    
Dukeling 19.08.2013 07:09
quelle
1

Wenn Sie den Fehler lokal behandeln, ist if ... else sauberer. Wenn die Funktion, bei der der Fehler auftritt, den Fehler nicht behandelt, wird eine Ausnahme ausgelöst, die an eine höhere Person in der Aufrufkette weitergegeben wird.

    
Pete Becker 19.08.2013 13:06
quelle
0

Zunächst wird Ihr erster Code mit der if-Anweisung das Programm beenden, falls der neue Operator [] wegen einer nicht behandelten Ausnahme eine Ausnahme auslöst. Sie können dies beispielsweise hier überprüfen: Ссылка

Auch in vielen anderen Fällen werden Ausnahmen ausgelöst, nicht nur, wenn die Zuweisung fehlgeschlagen ist und ihr Hauptmerkmal (in meinen Augen) die Steuerung in der Anwendung nach oben verschiebt (an Stelle, wo die Ausnahme behandelt wird). Ich empfehle Ihnen, mehr über Ausnahmen zu lesen, gutes Lesen wäre "Effektiveres C ++" von Scott Meyers, es gibt ein großes Kapitel über Ausnahmen.

    
Dino 19.08.2013 06:49
quelle