Obwohl es Exceptions im C++ Standard schon etliche Jahre gibt, werden diese in größeren Projekten oft nicht eingesetzt. Im folgenden Artikel möchte ich das Für und Wider erörtern und mit gängigen Vorurteilen aufräumen.

try {
    funktion();
   ...
} catch (const std::invalid_argument& e) {
    std::cerr << "Falsches Argument:"  << e.what() << std::endl;
} catch (const std::range_error& e) {
    std::cerr << "Ungültiger Bereich:" << e.what() << std::endl;
} catch (...) {
    std::cerr << "Sonstiger Fehler" << std::endl;
}

Gängige Vorurteile

  1. Die Behandlung von Ausnahmen ist codeintensiver (mehr Schreibarbeit)
    Falsch. Ein sinnvolles try/catch braucht ist sogar weniger Code als ein sinnvolles if/else if/elsefür alle möglichen Fehlercodes. Fehlercodes werden aber oft nicht vollständig überprüft oder gar ganz weggelassen, was der Qualität des Codes nicht gerade zuträglich ist. Exceptions dagegen zwingen zu einer durchdachten Fehlerbehandlung.
  2. Exceptions machen den Code langsam
    Falsch. Wenn Exceptions richtig eingesetzt werden, sollten sie für Ausnahmen im Programmablauf verwendet werden. Die Ausführungsgeschwindigkeit des „Gut“-Pfades (in dem keine Ausnahmen geworfen werden) leidet nicht darunter. Wenn also die Exception die Ausnahme und nicht die Regel ist, hat man nichts zu befürchten.
  3. Das Resourcen-Handling ist bei Excptions aufwändiger
    Falsch. Wenn RAII (Resource Acquisition Is Initialization) korrekt verwendet wird, muss man sich sogar weniger Sorgen um Aufräumarbeiten machen, als unter Java und C# – der Destruktor räumt die Objekte ohne Weiteres Zutun brav auf.
  4. Exception blähen das Binary auf
    Leider wahr. Nichts ist umsonst. Der Ausführungscode ist tatsächlich etwas größer. Dies sollte in heutiger Zeit aber kein ausschlaggebendes Argument mehr sein – selbst für Embedded-Programmierung.

Vorteile von Exceptions

  • Fehler können genau da behandelt werden, wo es Sinn macht
  • Exceptions müssen behandelt werden
  • Mehrdeutigkeiten werden vermieden (RetCode=3 mag in einem Fall OK, in anderem ein bestimmter Fehler sein)
  • Es können Fehler-Objekte anstatt simplen Zahlen verwendet werden

Caveat Exception Safety

Das Behandeln von Ausnahmen beim Erstellen von Objekten, also im Konstruktor, ist mit Vorsicht zu genießen, da in diesem Fall das Objekt noch nicht vollständig erzeugtist und der Destruktor es daher auch nicht aufräumen

kann. Es entstehen Memory-Leaks. Das Werfen von Ausnahmen im Konstruktor ist daher generell keine gute Idee.
Die Objekterzeugung Exception Safe zu machen, ist nicht ganz trivial, vor allem dann nicht, wenn sie erhalten bleiben soll, wenn die Klasse irgendwann erweitert wird. Daher kann eine einfache Möglichkeit sein, alles im Konstruktor zu unterlassen, was zu einer Ausnahme führen kann, die nicht abgefangen werden kann.
Im Allgemeinen wird zwischen verschiedenen Stufen von Exception Safety unterschieden (siehe Wikipedia):

  • No exception safety
  • Minimal exception safety (no-leak guarantee)
  • Basic exception safety
  • Commit or rollback semantics (strong exception safety/no-change guarantee)
  • Failure transparency (throw guarantee)

Gründe gegen Exceptions

  • Konsistenz: Es macht wenig Sinn, wenn eine bestimmte Methode einer Bibliothek Ausnahmen wirft, wenn dies im Rest der Bibliothek nicht der Fall ist. Dies würde die Verwendbarkeit einschränken. Qt verwendet aus diesem historischen Grund z.B. nur in neueren Bibliotheken Exceptions.
  • Unwissenheit: Wer sich mit der Behandlung von Ausnahmen nicht auskennt, sollte lieber erst mit Beispielen üben, bevor Exceptions an vorderster Front eingesetzt werden.

Fazit

Insgesamt führt Exceptions im Allgemeinen zu einer besseren Codequalität, da man das Fehlerhandling gezielter und duchdachter gestaltet. Aus heutiger Sicht gibt es meiner Meinung nach kaum haltbare Argumente, Exceptions nicht zu verwenden.

Quellen