Freigeben über


Fehler und Ausnahmebehandlung modernes (C++)

Die bevorzugte Methode zum Melden und Behandeln von logischen Fehlern und Laufzeitfehlern soll in modernen C++ in den meisten Szenarien Ausnahmen verwenden.Dies gilt besonders, wenn der Stapel zwischen der Funktion, die den Fehler entdeckt und die Funktion, die den Kontext zu wissen, wie es diesen zu behandeln hat mehrere Funktionsaufrufe enthalten kann.Ausnahmen bieten eine formale, genau definierte Methode für Code, der erkennt Fehler, die Informationen der Aufrufliste übergeben.

Programmfehler sind im Allgemeinen in zwei Kategorien unterteilt: logische Fehler, die verursacht werden durch Fehler, z. B. Programmierung, ein "Index außerhalb des gültigen Bereichs" Fehler und Laufzeitfehler, die außerhalb der Kontrolle des Programmierers, z. B. "network Service unavailable"-Fehler.In C-Programmierung und in COM wird Fehlerberichterstattung verwaltet, entweder einen Wert, der einen Fehlercode oder für eine bestimmte Funktion einen Statuscode zurückgeben oder Festlegen einer globalen Variablen, die der Aufrufer optional abrufen kann, nach jedem Funktionsaufruf um festzustellen, ob Fehler gemeldet wurden.Z. B. COM-Programmierung verwendet den HRESULT-Rückgabewert Fehler an den Aufrufer zu kommunizieren, und die Win32-API hat die GetLastError-Funktion, um den letzten Fehler abzurufen, der von der Aufrufliste gemeldet wurde.In beiden Fällen liegt es an den Aufrufer den Code erkennen und entsprechend darauf reagieren.Wenn der Aufrufer den Fehlercode nicht explizit verarbeitet, könnte das Programm crash ohne Warnung oder weiterhin mit fehlerhaften Daten führen und falsche Ergebnisse.

Ausnahmen werden in der modernen C++ aus folgenden Gründen bevorzugt:

  • Eine Ausnahme erzwingt aufrufenden Code eine Fehlerbedingung erkennen und umgehen.Unbehandelte Ausnahmen die Programmausführung anzuhalten.

  • Eine Ausnahme springt an die Stelle der Aufrufliste, die den Fehler behandeln kann.Fortgeschrittene Funktionen können die Ausnahme übertragen lassen.Sie haben nicht die Koordination mit anderen Schichten.

  • Der Ausnahmemechanismus Stapelentladung zerstört alle Objekte im Bereich nach eindeutig definierten Regeln, nachdem eine Ausnahme ausgelöst wird.

  • Eine Ausnahme ermöglicht eine saubere Trennung zwischen Code, der den Fehler erkennt und den Code, der den Fehler behandelt.

Im folgende Beispiel zeigt die notwendige Syntax für das Auslösen und Abfangen von Ausnahmen in C++.

 
#include <stdexcept>
#include <limits>
#include <iostream>
 
using namespace std;
class MyClass
{
public:
   void MyFunc(char c)
   {
      if(c < numeric_limits<char>::max())
         throw invalid_argument("MyFunc argument too large.");
      //...
   }
};

int main()
{
   try
   {
      MyFunc(256); //oops!
   }
 
   catch(invalid_argument& e)
   {
      cerr << e.what() << endl;
      return -1;
   }
   //...
   return 0;
}

Ausnahmen in C++ ähneln denen, die in Sprachen wie c# und Java.In der try blockieren, wenn eine Ausnahme ist ausgelöst, wird es gefangen durch das erste verknüpfte catch Block, dessen Typ, der die Ausnahme übereinstimmt.Mit anderen Worten, springt von der throw -Anweisung, um die catch Anweisung.Wenn keine nutzbare Catch-Block gefunden wird, std::terminate wird aufgerufen und das Programm beendet.In C++ kann beliebigen Typs ausgelöst werden; Wir empfehlen jedoch einen Typ werfen, die direkt oder indirekt abgeleitet std::exception.Im vorherigen Beispiel, den Ausnahmetyp, werden Invalid_argument, ist definiert in der Standardbibliothek in den <stdexcept> Header-Datei.C++ bietet keine und erfordert keine, eine finally Block, um sicherzustellen, dass alle Ressourcen freigegeben werden, wenn eine Ausnahme ausgelöst wird.Die Resource-Acquisition ist Initialisierung (RAII) Idiom, das intelligente Zeiger verwendet, die erforderliche Funktionen für die Ressourcenbereinigung von bietet.Weitere Informationen finden Sie unter Gewusst wie: Entwurf zur Ausnahmesicherheit.Informationen über die C++-Stapelentladung Mechanismus finden Sie unter Ausnahmen und Stapelentladung in C++.

Grundlegende Richtlinien

Robuste Fehlerbehandlung ist in jeder Programmiersprache eine Herausforderung.Obwohl Ausnahmen mehrere Features, die gute Fehlerbehandlung zu unterstützen bereit, können nicht sie die Arbeit für Sie tun.Um die Vorteile von Ausnahmeverfahren Beachten Sie Ausnahmen Sie Code entwerfen.

  • Assertionen, um nach Fehlern zu suchen, die niemals auftreten dürften.Verwenden Sie Ausnahmen, um die Fehlerprüfung für möglicherweise, die auftretende Fehler, z. B. in der Eingabeüberprüfung über Parameter des öffentlichen Funktionen.Weitere Informationen finden Sie unter Exceptions VS. Assertions.

  • Verwenden Sie Ausnahmen, wenn der Code, der den Fehler behandelt getrennt werden möglicherweise aus dem Code, der den Fehler erkennt eine oder mehrere dazwischen liegenden Funktionsaufrufe.Prüfen Sie, ob Fehlercodes stattdessen in leistungskritischen Schleifen verwendet werden, wenn Code, der den Fehler behandelt der Code eng gekoppelt ist, das es erkennt.Weitere Informationen über die Verwendung von Ausnahmen finden Sie unter When Not to Use Exceptions.

  • Für jede Funktion, die möglicherweise werfen oder eine Ausnahme weitergeben, bieten eine der drei Ausnahme Garantien: starke Garantie, die grundlegende Garantie oder Garantie Nothrow (Noexcept).Weitere Informationen finden Sie unter Gewusst wie: Entwurf zur Ausnahmesicherheit.

  • Ausnahmen von Wert, als Verweis zu fangen.Fangen Sie nicht ab, was Sie nicht behandeln können.Weitere Informationen finden Sie unter Richtlinien für das Auslösen und Abfangen von Ausnahmen (C++).

  • Verwenden Sie keine Ausnahme-Spezifikationen, die in c werden ++ 11.Weitere Informationen finden Sie unter Exception specifications and noexcept.

  • Verwenden Sie Standardbibliothek Ausnahmetypen, wenn sie anwenden.Leiten Sie benutzerdefinierte Ausnahmetypen, die von der Exception-Klasse Hierarchie.Weitere Informationen finden Sie unter Gewusst wie: Verwenden Sie die standardmäßige bibliotheks-Ausnahmeobjekte.

  • Ermöglichen Sie Ausnahmen zu entfliehen Destruktoren oder Speicherfreigabe Funktionen nicht.

Ausnahmen und performance

Der Ausnahmemechanismus hat eine sehr geringe Kosten, wenn keine Ausnahme ausgelöst wird.Wenn eine Ausnahme ausgelöst wird, ist die Kosten der Stack-Traversal und entladenen etwa vergleichbar mit den Kosten eines Funktionsaufrufs.Zusätzliche Datenstrukturen sind erforderlich, um die Aufrufliste nach verfolgen einen try -Block eingegeben wird und zusätzliche Anweisungen sind erforderlich, um den Stapel entladen, wenn eine Ausnahme ausgelöst wird.In den meisten Szenarien ist jedoch die Kosten in Performance und Speicherbedarf nicht signifikante.Die nachteilige Auswirkungen von Ausnahmen auf die Leistung ist wahrscheinlich nur in sehr eingeschränktem Speicher-Systemen erheblich sein, oder in leistungskritischen Schleifen, in denen ein Fehler ist wahrscheinlich regelmäßig auftreten und Code zur Verarbeitung ist eng mit dem Code, der es meldet.In jedem Fall ist es unmöglich, die tatsächliche Kosten der Ausnahmen zu kennen, ohne profiling und messen.Auch in den seltenen Fällen, wenn die Kosten erheblich, können Sie wiegen es gegen die erhöhte Richtigkeit, leichter Verwaltbarkeit und andere Vorteile, die durch eine gut durchdachte Ausnahmerichtlinie bereitgestellt werden.

Ausnahmen VS. Assertionen

Ausnahmen und Assertionen sind zwei verschiedene Mechanismen zum Erkennen von Laufzeitfehlern in einem Programm.Assertionen, um Bedingungen während der Entwicklung zu testen, die nie sein sollten, wenn Ihr Code richtig ist.Es gibt keinen Sinn, eine solche Fehlermeldung mithilfe eine Ausnahme, da der Fehler weist darauf hin, daß etwas im Code festgelegt werden, behandeln und keine Bedingung, die das Programm zur Wiederherstellung zur Laufzeit darstellen.Ein Assert beendet die Ausführung bei der Anweisung, so dass Sie den Status des Programms im Debugger kontrollieren können; eine Ausnahme wird die Ausführung aus dem ersten entsprechenden Catch-Handler.Verwenden Sie Ausnahmen, um Fehlerzustände zu prüfen, die zur Laufzeit auftreten können, selbst wenn der Code korrekt, z. B. ist "Datei nicht gefunden" oder "nicht genügend Arbeitsspeicher." Sie möchten von diesen Bedingungen wiederherzustellen, selbst wenn die Wiederherstellung nur eine Meldung in ein Protokoll gibt und das Programm beendet.Überprüfen Sie immer die Argumente für Öffentliche Funktionen mithilfe von Ausnahmen.Auch wenn Ihre Funktion fehlerfrei ist, können Sie vollständige Kontrolle über Argumente keinen, die ein Benutzer auf sie übertragen könnten.

C++-Ausnahmen im Vergleich zu Windows-SEH-Ausnahmen

C- und C++-Programme können die strukturierte Ausnahmebehandlung (SEH) im Windows-Betriebssystem verwenden.Die Konzepte in SEH ähneln denen in C++-Ausnahmen, SEH verwendet die __try, __except, und __finally erstellt, statt try und catch.C++-Ausnahmen werden in Visual C++ für SEH implementiert.Jedoch, wenn Sie C++-Code schreiben, verwenden Sie die Syntax die C++-Ausnahme.

Weitere Informationen über SEH finden Sie unter Strukturierte Ausnahmebehandlung (C++).

Ausnahmespezifikationen und noexcept

Ausnahmespezifikationen wurden in C++ eingeführt, als eine Möglichkeit, die Ausnahmen angeben, die eine Funktion Ausnahmen auslösen könnte.Allerdings Ausnahmespezifikationen problematisch in der Praxis erwiesen und sind veraltet, in der C ++ 11 Draft-Standard.Es wird empfohlen, nicht zu Ausnahmespezifikationen außer verwenden throw(), die angibt, dass die Ausnahme keine Ausnahmen zu entkommen ermöglicht.Bei Verwendung der Ausnahmespezifikationen des Typs throw(Type), beachten Sie, Visual C++ weicht von der Standard in gewisser Weise.Weitere Informationen finden Sie unter Ausnahmespezifikation.Die noexcept Bezeichner wird in C ++ 11 als bevorzugte Alternative zu den throw().

Siehe auch

Konzepte

Gewusst wie: Schnittstelle zwischen Ausnahmem und Nicht-Ausnahmem Code

Weitere Ressourcen

Willkommen zurück in C++ modernes (C++)

C++-Sprachreferenz

C++-Standardbibliothek-Referenz