Ausnahme Sicherheit
Vorläufige Warnung: Die Ausnahmesicherheit ist nicht vollständig! Übliche Fälle sollten funktionieren, aber Klassen können trotzdem auslaufen oder sogar abstürzen.
Qt selbst wird keine Ausnahmen auslösen. Stattdessen werden Fehlercodes verwendet. Darüber hinaus haben einige Klassen für den Benutzer sichtbare Fehlermeldungen, zum Beispiel QIODevice::errorString() oder QSqlQuery::lastError(). Dies hat historische und praktische Gründe - das Einschalten von Ausnahmen kann die Größe der Bibliothek um über 20% erhöhen.
Die folgenden Abschnitte beschreiben das Verhalten von Qt, wenn die Ausnahmeunterstützung zur Kompilierzeit aktiviert ist.
Ausnahmesichere Module
Behältnisse
Die Containerklassen von Qt sind im Allgemeinen ausnahmsneutral. Sie geben jede Ausnahme, die innerhalb ihres enthaltenen Typs T
auftritt, an den Benutzer weiter, während ihr interner Zustand gültig bleibt.
Beispiel:
QList<QString> list; ... try { list.append("hello"); } catch (...) { } // list is safe to use - the exception did not affect it.
Ausnahmen von dieser Regel sind Container für Typen, die bei Zuweisungs- oder Kopierkonstruktionen auslösen können. Für diese Typen sind Funktionen, die den Container verändern und einen Wert zurückgeben, unsicher:
MyType s = list.takeAt(2);
Wenn während der Zuweisung von s
eine Ausnahme auftritt, wird der Wert bei Index 2 bereits aus dem Container entfernt, aber noch nicht s
zugewiesen. Er ist ohne Chance auf Wiederherstellung verloren.
Der korrekte Weg, ihn zu schreiben:
MyType s = list.at(2); list.removeAt(2);
Wenn die Zuweisung fehlschlägt, enthält der Container immer noch den Wert; es gibt keinen Datenverlust.
Beachten Sie, dass implizit gemeinsam genutzte Qt-Klassen in ihren Zuweisungsoperatoren oder Kopierkonstruktoren nicht auslösen, so dass die obige Einschränkung nicht gilt.
Behandlung außerhalb des Speichers
Die meisten Desktop-Betriebssysteme haben ein Overcommit von Speicher. Das bedeutet, dass malloc()
oder operator new
einen gültigen Zeiger zurückgeben, obwohl zur Allokationszeit nicht genügend Speicher verfügbar ist. Auf solchen Systemen wird keine Ausnahme des Typs std::bad_alloc
ausgelöst.
Auf allen anderen Betriebssystemen löst Qt eine Ausnahme vom Typ std::bad_alloc aus, wenn eine Zuweisung fehlschlägt. Allokationen können fehlschlagen, wenn dem System der Speicher ausgeht oder nicht genügend kontinuierlicher Speicher zur Verfügung steht, um die angeforderte Größe zu allozieren.
Ausnahmen von dieser Regel sind dokumentiert. Zum Beispiel erstellen die Konstruktoren von QImage ein null Image, wenn nicht genügend Speicher vorhanden ist, anstatt eine Ausnahme zu machen.
Behebung von Ausnahmen
Derzeit ist der einzige unterstützte Anwendungsfall für die Wiederherstellung von in Qt ausgelösten Exceptions (z.B. aufgrund von Speichermangel) das Verlassen der Ereignisschleife und die Durchführung von Aufräumarbeiten vor dem Beenden der Anwendung.
Typischer Anwendungsfall:
QApplication app(argc, argv); ... int ret; try { ret = app.exec(); } catch (const std::bad_alloc &) { // clean up here, e.g. save the session // and close all config files. return EXIT_FAILURE; // exit the application } ... return ret;
Nachdem eine Exception ausgelöst wurde, könnte die Verbindung zum Windowing-Server bereits geschlossen sein. Es ist nicht sicher, eine GUI-bezogene Funktion aufzurufen, nachdem eine Ausnahme abgefangen wurde.
Ausnahmen im Client-Code
Signale und Slots
Das Auslösen einer Exception in einem Slot, der von Qt's Signal-Slot-Verbindungsmechanismus aufgerufen wird, wird als undefiniertes Verhalten betrachtet, es sei denn, es wird innerhalb des Slots behandelt:
State state; StateListener stateListener; // OK; the exception is handled before it leaves the slot. QObject::connect(&state, SIGNAL(stateChanged()), &stateListener, SLOT(throwHandledException())); // Undefined behaviour; upon invocation of the slot, the exception will be propagated to the // point of emission, unwinding the stack of the Qt code (which is not guaranteed to be exception safe). QObject::connect(&state, SIGNAL(stateChanged()), &stateListener, SLOT(throwUnhandledException()));
Wenn der Slot direkt aufgerufen wurde, wie ein normaler Funktionsaufruf, können Exceptions verwendet werden. Dies liegt daran, dass der Verbindungsmechanismus beim direkten Aufruf von Slots umgangen wird:
State state; StateListener stateListener;// ...try { // OK; Slot direkt aufrufen.stateListener.throwException(); } catch (...) { qDebug() << "Handling exception not caught in slot."; }
© 2025 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.