Techniken zur Fehlerbehebung
Hier stellen wir Ihnen einige nützliche Tipps vor, die Ihnen beim Debuggen Ihrer Qt-basierten Software helfen sollen.
Qt für die Fehlersuche konfigurieren
Bei der Konfiguration von Qt für die Installation kann sichergestellt werden, dass es mit Debug-Symbolen kompiliert wird, die das Aufspüren von Fehlern in Anwendungen und Bibliotheken erleichtern. Auf einigen Plattformen führt die Kompilierung von Qt im Debug-Modus jedoch dazu, dass Anwendungen größer als gewünscht werden.
Debugging unter macOS und Xcode
Debugging mit/ohne Frameworks
Die grundlegenden Informationen, die Sie über Debug-Bibliotheken und Frameworks wissen müssen, finden Sie auf developer.apple.com in: Apple Technical Note TN2124.
Beim Kompilieren von Qt werden standardmäßig Frameworks erstellt, und innerhalb des Frameworks finden Sie sowohl eine Release- als auch eine Debug-Version (z. B. „ QtCore “ und „QtCore_debug“). Wenn du beim Kompilieren von Qt das Flag „ -no-framework “ übergibst, werden für jede Qt-Bibliothek zwei dylibs erstellt (z. B. libQtCore.4.dylib und libQtCore_debug.4.dylib).
Was beim Verknüpfen geschieht, hängt davon ab, ob Sie Frameworks verwenden oder nicht. Wir sehen keinen zwingenden Grund, eine der beiden Varianten gegenüber der anderen zu empfehlen.
Mit Frameworks:
Da sich die Release- und Debug-Bibliotheken im Framework befinden, wird die App einfach gegen das Framework verknüpft. Wenn Sie die App dann im Debugger ausführen, erhalten Sie entweder die Release-Version oder die Debug-Version, je nachdem, ob Sie „ DYLD_IMAGE_SUFFIX “ gesetzt haben. Wenn Sie dies nicht tun, erhalten Sie standardmäßig die Release-Version (d. h. nicht _debug). Wenn Sie „ DYLD_IMAGE_SUFFIX=_debug “ setzen, erhalten Sie die Debug-Version.
Ohne Frameworks:
Wenn du qmake anweist, eine Makefile-Datei mit der Debug-Konfiguration zu generieren, wird diese mit der _debug-Version der Bibliotheken verknüpft und es werden Debug-Symbole für die Anwendung generiert. Das Ausführen dieses Programms in GDB funktioniert dann wie das Ausführen von GDB auf anderen Plattformen, und du kannst innerhalb von Qt Traces erstellen.
Von Qt erkannte Befehlszeilenoptionen
Wenn Sie eine Qt-Anwendung ausführen, können Sie verschiedene Befehlszeilenoptionen angeben, die beim Debuggen helfen können. Diese werden von ` QApplication` erkannt.
| Option | Beschreibung |
|---|---|
-nograb | Die Anwendung darf niemals the mouse oder the keyboard abgreifen. Diese Option ist standardmäßig gesetzt, wenn das Programm unter Linux im Debugger „ gdb “ ausgeführt wird. |
-dograb | Ignoriere alle impliziten oder expliziten „ -nograb “. „ -dograb “ hat Vorrang vor „ -nograb “, selbst wenn „ -nograb “ als letztes in der Befehlszeile steht. |
Von Qt erkannte Umgebungsvariablen
Zur Laufzeit erkennt eine Qt-Anwendung zahlreiche Umgebungsvariablen, von denen einige beim Debuggen hilfreich sein können:
| Variable | Beschreibung |
|---|---|
QT_DEBUG_PLUGINS | Setzen Sie diese Variable auf einen Wert ungleich Null, damit Qt Diagnoseinformationen zu jedem (C++-)Plugin ausgibt, das es zu laden versucht. |
QML_IMPORT_TRACE | Setzen Sie diese Variable auf einen Wert ungleich Null, damit QML Diagnoseinformationen aus dem Import-Lademechanismus ausgibt. |
QT_HASH_SEED | Setzen Sie diese Variable auf einen ganzzahligen Wert, um die Funktionen „ QHash “ und „ QSet “ zu deaktivieren, die bei jedem Anwendungsstart eine neue zufällige Reihenfolge verwenden, was in manchen Fällen das Testen und Debuggen erschweren kann. |
QT_WIN_DEBUG_CONSOLE | Unter Windows sind GUI-Anwendungen nicht an eine Konsole angebunden, sodass die in „ stdout “ und „ stderr “ geschriebene Ausgabe für den Benutzer nicht sichtbar ist. IDEs leiten die Ausgabe in der Regel um und zeigen sie an, doch beim Ausführen einer Anwendung über die Befehlszeile geht die Debug-Ausgabe verloren. Um Zugriff auf die Ausgabe zu erhalten, setzen Sie diese Umgebungsvariable auf „ new “, damit die Anwendung eine neue Konsole zuweist, oder auf „ attach “, damit die Anwendung versucht, sich an die Konsole des übergeordneten Prozesses anzuhängen. |
Warn- und Debugging-Meldungen
Qt enthält globale C++-Makros zum Ausgeben von Warn- und Debug-Text. Die einfachen Makros verwenden eine Standard logging category; mit den Makros für kategorisiertes Logging können Sie die Kategorie angeben. Sie können sie für folgende Zwecke verwenden:
| Einfaches Makro | Kategorisiertes Makro | Zweck |
|---|---|---|
| qDebug() | qCDebug() | Wird zum Schreiben benutzerdefinierter Debug-Ausgaben verwendet |
| qInfo() | qCInfo() | Wird für Informationsmeldungen verwendet |
| qWarning() | qCWarning() | Wird verwendet, um Warnungen und behebbare Fehler in Ihrer Anwendung oder Bibliothek zu melden |
| qCritical() | qCCritical() | Wird zum Schreiben kritischer Fehlermeldungen und zum Melden von Systemfehlern verwendet |
| qFatal() | - | Wird zum Ausgeben von Meldungen über schwerwiegende Fehler kurz vor dem Beenden verwendet |
Wenn Sie die Header-Datei <QtDebug> einbinden, kann das Makro „ qDebug() “ auch als Ausgabestrom verwendet werden. Beispiel:
qDebug() << "Widget" << widget << "at position" << widget->pos();Die Qt-Implementierung dieser Makros gibt unter Unix/Linux und macOS die Ausgabe an „ stderr “ weiter. Unter Windows wird der Text bei einer Konsolenanwendung an die Konsole gesendet, andernfalls an den Debugger.
Standardmäßig wird nur die Meldung ausgegeben. Sie können zusätzliche Informationen einfügen, indem Sie die Umgebungsvariable ` QT_MESSAGE_PATTERN ` setzen. Beispiel:
QT_MESSAGE_PATTERN="[%{time process} %{type}] %{appname} %{category} %{function} - %{message}"Das Format ist unter ` qSetMessagePattern()` dokumentiert. Sie können auch einen eigenen Meldungshandler mithilfe von ` qInstallMessageHandler()` installieren.
Wenn die Umgebungsvariable ` QT_FATAL_WARNINGS ` gesetzt ist, beendet ` qWarning()` die Ausführung nach der Ausgabe der Warnmeldung. Dies erleichtert das Abrufen eines Backtrace im Debugger.
qDebug(), qInfo() und qWarning() sind Debugging-Werkzeuge. Sie können durch die Definition von QT_NO_DEBUG_OUTPUT, QT_NO_INFO_OUTPUT oder QT_NO_WARNING_OUTPUT während der Kompilierung herauskompiliert werden.
Die Debugging-Funktionen QObject::dumpObjectTree() und QObject::dumpObjectInfo() sind oft nützlich, wenn sich eine Anwendung seltsam verhält oder anzeigt. Sie sind nützlicher, wenn Sie object names verwenden, als wenn Sie es nicht tun, aber oft sind sie auch ohne Namen nützlich.
In QML erfüllt ` dumpItemTree()` denselben Zweck.
Unterstützung für den qDebug()-Stream-Operator bereitstellen
Sie können den von ` qDebug()` verwendeten Stream-Operator implementieren, um Debugging-Unterstützung für Ihre Klassen bereitzustellen. Die Klasse, die den Stream implementiert, ist ` QDebug`. Verwenden Sie ` QDebugStateSaver `, um die Formatierungsoptionen des Streams vorübergehend zu speichern. Verwenden Sie ` nospace()` und ` QTextStream manipulators `, um die Formatierung weiter anzupassen.
Hier ist ein Beispiel für eine Klasse, die eine 2D-Koordinate darstellt.
QDebug operator<<(QDebug dbg, const Coordinate &c)
{
QDebugStateSaver saver(dbg);
dbg.nospace() << "(" << c.x() << ", " << c.y() << ")";
return dbg;
}Die Integration benutzerdefinierter Typen in das Metaobjektsystem von Qt wird im Dokument „Erstellen benutzerdefinierter Qt-Typen“ ausführlicher behandelt.
Debugging-Makros
Die Header-Datei „ <QtGlobal> “ enthält einige Debugging-Makros und „ #defines“.
Drei wichtige Makros sind:
- Q_ASSERT(cond), wobei
condein boolescher Ausdruck ist, schreibt die Warnung „ASSERT:‚cond‘ in Datei xyz.cpp, Zeile 234“ und beendet das Programm, wenncondfalsch ist. - Q_ASSERT_X(cond, where, what), wobei „
cond“ ein boolescher Ausdruck, „where“ eine Position und „what“ eine Meldung ist, gibt die Warnung „ASSERT-Fehler inwhere: ‚what‘, Datei xyz.cpp, Zeile 234“ aus und beendet das Programm, wenn „cond“ falsch ist. - Q_CHECK_PTR(ptr), wobei
ptrein Zeiger ist. Gibt die Warnung „In Datei xyz.cpp, Zeile 234: Nicht genügend Speicher“ aus und beendet das Programm, wennptrden Wert 0 hat.
Diese Makros sind nützlich, um Programmfehler zu erkennen, z. B. wie folgt:
char *alloc(int size)
{
Q_ASSERT(size > 0);
char *ptr = new char[size];
Q_CHECK_PTR(ptr);
return ptr;
}Q_ASSERT(), Q_ASSERT_X() und Q_CHECK_PTR() werden zu nichts expandiert, wenn QT_NO_DEBUG bei der Kompilierung definiert ist. Aus diesem Grund sollten die Argumente dieser Makros keine Nebenwirkungen haben. Hier ist eine falsche Verwendung von Q_CHECK_PTR():
char *alloc(int size)
{
char *ptr;
Q_CHECK_PTR(ptr = new char[size]); // WRONG
return ptr;
}Wird dieser Code mit definiertem ` QT_NO_DEBUG ` kompiliert, wird der Code im Ausdruck ` Q_CHECK_PTR()` nicht ausgeführt und `alloc` gibt einen nicht initialisierten Zeiger zurück.
Die Qt-Bibliothek enthält Hunderte interner Prüfungen, die Warnmeldungen ausgeben, wenn ein Programmierfehler erkannt wird. Wir empfehlen daher, bei der Entwicklung von Qt-basierter Software eine Debug-Version von Qt zu verwenden.
Logging und „ categorized logging “ sind auch in QML möglich.
Häufige Fehler
Es gibt einen Fehler, der so häufig auftritt, dass er hier erwähnt werden sollte: Wenn Sie das Makro „ Q_OBJECT “ in eine Klassendeklaration einfügen und den Meta-Object Compiler (moc) ausführen, aber vergessen, den von „ moc “ generierten Objektcode in Ihre ausführbare Datei einzubinden, erhalten Sie sehr verwirrende Fehlermeldungen. Jeder Linkfehler, der das Fehlen von „ vtbl “, „ _vtbl “, „ __vtbl “ oder Ähnlichem bemängelt, ist wahrscheinlich auf dieses Problem zurückzuführen.
© 2026 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.