Namespaces
Variants

Exceptions

From cppreference.net
C++ language
General topics
Flow control
Conditional execution statements
Iteration statements (loops)
Jump statements
Functions
Function declaration
Lambda function expression
inline specifier
Dynamic exception specifications ( until C++17* )
noexcept specifier (C++11)
Exceptions
Namespaces
Types
Specifiers
constexpr (C++11)
consteval (C++20)
constinit (C++20)
Storage duration specifiers
Initialization
Expressions
Alternative representations
Literals
Boolean - Integer - Floating-point
Character - String - nullptr (C++11)
User-defined (C++11)
Utilities
Attributes (C++11)
Types
typedef declaration
Type alias declaration (C++11)
Casts
Memory allocation
Classes
Class-specific function properties
Special member functions
Templates
Miscellaneous

Die Ausnahmebehandlung bietet eine Möglichkeit, die Kontrolle und Informationen von einem Punkt in der Ausführung eines Programms an einen Handler zu übertragen, der mit einem zuvor von der Ausführung passierten Punkt verbunden ist (mit anderen Worten, die Ausnahmebehandlung überträgt die Kontrolle den Aufrufstapel hinauf).

Die Auswertung eines throw -Ausdrucks wirft eine Exception. Exceptions können auch in anderen Kontexten geworfen werden.

Damit eine Ausnahme abgefangen werden kann, muss der throw -Ausdruck innerhalb eines try -Blocks stehen, und der try -Block muss einen Handler enthalten, der zum Typ des Ausnahmeobjekts passt.

Bei der Deklaration einer Funktion können die folgenden Spezifikationen angegeben werden, um die Arten von Ausnahmen einzuschränken, die eine Funktion werfen darf:

(bis C++17)
(seit C++11)

Fehler, die während der Ausnahmebehandlung auftreten, werden durch std::terminate und std::unexpected (until C++17) behandelt.

Inhaltsverzeichnis

Verwendung

Während throw -Ausdrücke verwendet werden können, um die Kontrolle an einen beliebigen Codeblock im Ausführungsstack zu übertragen, aus beliebigen Gründen (ähnlich wie std::longjmp ), ist ihre beabsichtigte Verwendung die Fehlerbehandlung.

Fehlerbehandlung

Das Werfen einer Exception wird verwendet, um Fehler aus Funktionen zu signalisieren, wobei "Fehler" typischerweise auf Folgendes beschränkt sind [1] [2] [3] :

  1. Verstöße gegen die Nachbedingungen, wie das Fehlschlagen bei der Erzeugung eines gültigen Rückgabewertobjekts.
  2. Verstöße gegen die Vorbedingungen einer anderen Funktion, die aufgerufen werden muss.
  3. (für nicht-private Memberfunktionen) Verstöße gegen die (Wieder-)Herstellung einer Klasseninvariante.

Insbesondere impliziert dies, dass Fehler von Konstruktoren (siehe auch RAII ) und der meisten Operatoren durch das Werfen von Exceptions gemeldet werden sollten.

Zusätzlich verwenden sogenannte wide contract Funktionen Ausnahmen, um unzulässige Eingaben anzuzeigen, zum Beispiel hat std::basic_string::at keine Vorbedingungen, wirft jedoch eine Ausnahme, um einen Index außerhalb des gültigen Bereichs anzuzeigen.

Ausnahmesicherheit

Nachdem eine Fehlerbedingung durch eine Funktion gemeldet wurde, können zusätzliche Garantien bezüglich des Programmzustands bereitgestellt werden. Die folgenden vier Stufen der Exception-Garantie werden allgemein anerkannt [4] [5] [6] , die strikte Obermengen voneinander sind:

  1. Nothrow- (oder Nofail-) Ausnahmesicherheitsgarantie — Die Funktion wirft niemals Ausnahmen. Nothrow (Fehler werden auf andere Weise gemeldet oder verborgen) wird von Destruktoren und anderen Funktionen erwartet, die während Stack-Unwinding aufgerufen werden können. Standardmäßig sind Destruktoren noexcept . (seit C++11) Nofail (die Funktion ist immer erfolgreich) wird von Swaps, Move-Konstruktoren und anderen Funktionen erwartet, die von jenen verwendet werden, die die starke Ausnahmesicherheitsgarantie bieten.
  2. Starke Ausnahmesicherheitsgarantie — Wenn die Funktion eine Ausnahme wirft, wird der Programmzustand auf den Zustand direkt vor dem Funktionsaufruf zurückgesetzt (zum Beispiel std::vector::push_back ).
  3. Grundlegende Ausnahmesicherheitsgarantie — Wenn die Funktion eine Ausnahme wirft, befindet sich das Programm in einem gültigen Zustand. Es treten keine Ressourcenlecks auf, und alle Objektinvarianten sind intakt.
  4. Keine Ausnahmesicherheitsgarantie — Wenn die Funktion eine Ausnahme wirft, befindet sich das Programm möglicherweise nicht in einem gültigen Zustand: Ressourcenlecks, Speicherbeschädigungen oder andere invariantenzerstörende Fehler können aufgetreten sein.

Generische Komponenten können zusätzlich eine ausnahmeneutrale Garantie bieten: Wenn eine Ausnahme von einem Template-Parameter ausgelöst wird (z.B. vom Compare -Funktionsobjekt in std::sort oder vom Konstruktor von T in std::make_shared ), wird sie unverändert an den Aufrufer weitergegeben.

Exception-Objekte

Während Objekte jedes vollständigen Typs und cv-Zeiger auf void als Ausnahmeobjekte geworfen werden können, werfen alle Standardbibliotheksfunktionen unbenannte Objekte als Wert, und die Typen dieser Objekte sind (direkt oder indirekt) von std::exception abgeleitet. Benutzerdefinierte Ausnahmen folgen üblicherweise diesem Muster. [7] [8] [9]

Um unnötiges Kopieren des Ausnahmeobjekts und Object Slicing zu vermeiden, ist die beste Praxis für Handler, Ausnahmen per Referenz zu fangen. [10] [11] [12] [13]

Hinweise

Feature-Test-Makro Wert Std Feature
__cpp_constexpr_exceptions 202411L (C++26) constexpr Exceptions

Externe Links

  1. H. Sutter (2004) "Wann und wie man Ausnahmen verwendet" in Dr. Dobb's
  2. H. Sutter, A. Alexandrescu (2004), "C++ Coding Standards", Punkt 70
  3. C++ Core Guidelines I.10: Verwenden Sie Ausnahmen, um einen Fehler bei der Ausführung einer erforderlichen Aufgabe zu signalisieren
  4. B. Stroustrup (2000), "The C++ Programming Language" Anhang E
  5. H. Sutter (2000) "Exceptional C++"
  6. D. Abrahams (2001) "Ausnahmesicherheit in generischen Komponenten"
  7. D. Abrahams (2001) "Fehler- und Ausnahmebehandlung"
  8. isocpp.org Super-FAQ "Was sollte ich werfen?"
  9. C++ Core Guidelines E.14: Verwenden Sie speziell entworfene benutzerdefinierte Typen als Ausnahmen (keine eingebauten Typen)
  10. C++ Core Guidelines E.15: Werfen Sie nach Wert, fangen Sie Ausnahmen aus einer Hierarchie per Referenz
  11. S. Meyers (1996) "More Effective C++" Punkt 13
  12. isocpp.org Super-FAQ "Was sollte ich fangen?"
  13. H. Sutter, A. Alexandrescu (2004) "C++ Coding Standards" Punkt 73