调试技巧
在此,我们将提供一些有用的提示,以帮助您调试基于 Qt 的软件。
配置 Qt 以进行调试
在配置Qt 安装时,可以确保其构建过程中包含调试符号,这有助于更轻松地追踪应用程序和库中的错误。不过,在某些平台上,以调试模式构建 Qt 会导致应用程序体积超出理想范围。
在 macOS 和 Xcode 中进行调试
使用或不使用框架进行调试
关于调试库和框架的基本知识,请参阅 developer.apple.com 上的《Apple 技术说明 TN2124》。
构建 Qt 时,框架会默认被构建,且在框架内部,您会发现发布版和调试版(例如,QtCore 和 QtCore_debug)。 如果在构建 Qt 时传递-no-framework 标志,则每个 Qt 库都会生成两个 dylib(例如 libQtCore.4.dylib 和 libQtCore_debug.4.dylib)。
链接时会发生什么,取决于您是否使用框架。我们认为没有充分的理由推荐其中一种而非另一种。
使用框架时:
由于发布版和调试版库都包含在框架中,应用程序只需与该框架进行链接即可。随后,当你在调试器中运行时,根据是否设置了 `DYLD_IMAGE_SUFFIX`,你会获得发布版或调试版。若未设置该选项,默认将获得发布版(即非 _debug 版本)。 若设置DYLD_IMAGE_SUFFIX=_debug ,则会获得调试版本。
不使用框架时:
当你指示qmake使用调试配置生成 Makefile 时,它会链接到库的 _debug 版本,并为应用程序生成调试符号。随后在 GDB 中运行该程序的效果将与其他平台上的 GDB 运行效果一致,并且你将能够追踪 Qt 内部的运行情况。
Qt 识别的命令行选项
运行 Qt 应用程序时,您可以指定若干有助于调试的命令行选项。这些选项由 `QApplication` 识别。
| 选项 | 描述 |
|---|---|
-nograb | 应用程序绝不应捕获the mouse 或the keyboard 。当程序在Linux下的gdb 调试器中运行时,此选项默认启用。 |
-dograb | 忽略任何隐式或显式的-nograb 。即使-nograb 是命令行中的最后一个选项,-dograb 也优先于-nograb 。 |
Qt 识别的环境变量
在运行时,Qt 应用程序会识别许多环境变量,其中一些对调试很有帮助:
| 变量 | 描述 |
|---|---|
QT_DEBUG_PLUGINS | 将其设置为非零值,可让 Qt 打印出其尝试加载的每个 (C++) 插件的诊断信息。 |
QML_IMPORT_TRACE | 将其设置为非零值,可让 QML 打印出有关导入加载机制的诊断信息。 |
QT_HASH_SEED | 将其设置为整数值,可禁用QHash 和QSet ,这些文件会在每次应用程序运行时采用新的随机排序,这在某些情况下可能会使测试和调试变得困难。 |
QT_WIN_DEBUG_CONSOLE | 在 Windows 上,GUI 应用程序未连接到控制台,因此写入stdout 和stderr 的输出对用户不可见。IDE 通常会重定向并显示输出,但在命令行上运行应用程序时,调试输出将丢失。 要访问这些输出,请将此环境变量设置为new ,以使应用程序分配一个新的控制台;或者设置为attach ,以使应用程序尝试连接到父进程的控制台。 |
警告和调试消息
Qt 包含用于输出警告和调试文本的全局 C++ 宏。普通宏使用默认的logging category ;分类日志宏允许您指定类别。您可以将其用于以下目的:
| 普通宏 | 分类宏 | 用途 |
|---|---|---|
| qDebug() | qCDebug() | 用于编写自定义调试输出 |
| qInfo() | qCInfo() | 用于信息性消息 |
| qWarning() | qCWarning() | 用于报告应用程序或库中的警告和可恢复错误 |
| qCritical() | qCCritical() | 用于编写严重错误消息并报告系统错误 |
| qFatal() | - | 用于在退出程序前不久输出关于致命错误的消息 |
如果您包含 <QtDebug> 头文件,则还可以将qDebug() 宏用作输出流。例如:
qDebug() << "Widget" << widget << "at position" << widget->pos();在 Unix/Linux 和 macOS 系统上,Qt XML 对这些宏的实现会将内容输出到stderr 输出流中。在 Windows 系统上,如果是控制台应用程序,文本将发送到控制台;否则,将发送到调试器。
默认情况下,仅打印消息本身。您可以通过设置QT_MESSAGE_PATTERN 环境变量来包含额外信息。例如:
QT_MESSAGE_PATTERN="[%{time process} %{type}] %{appname} %{category} %{function} - %{message}"格式已在qSetMessagePattern() 中有详细说明。您还可以通过qInstallMessageHandler() 安装自定义的消息处理程序。
如果设置了QT_FATAL_WARNINGS 环境变量,qWarning()会在打印警告消息后退出。这使得在调试器中获取回溯信息变得容易。
qDebug()、qInfo() 和qWarning() 均为调试工具。通过在编译时定义QT_NO_DEBUG_OUTPUT 、QT_NO_INFO_OUTPUT 或QT_NO_WARNING_OUTPUT ,可以将其从程序中编译掉。
当应用程序出现异常表现时,调试函数QObject::dumpObjectTree() 和QObject::dumpObjectInfo() 通常非常有用。如果定义了object names ,这些函数会更加实用;但即使不定义,它们通常也依然有用。
在 QML 中,dumpItemTree() 具有相同的功能。
为 qDebug() 流运算符提供支持
您可以实现qDebug() 所使用的流运算符,为您的类提供调试支持。实现该流的类是QDebug 。使用QDebugStateSaver 临时保存流的格式化选项。使用nospace() 和QTextStream manipulators 进一步自定义格式。
以下是一个表示二维坐标的类的示例。
QDebug operator<<(QDebug dbg, const Coordinate &c)
{
QDebugStateSaver saver(dbg);
dbg.nospace() << "(" << c.x() << ", " << c.y() << ")";
return dbg;
}关于自定义类型与 Qt 元对象系统的集成,在《创建自定义 Qt 类型》文档中有更深入的探讨。
调试宏
头文件<QtGlobal> 包含一些调试宏和#define。
其中三个重要的宏是:
- Q_ASSERT(cond),其中
cond是一个布尔表达式,如果cond为 false,则会输出警告“ASSERT:'cond' in file xyz.cpp, line 234”并退出。 - Q_ASSERT_X(cond, where, what),其中
cond是一个布尔表达式,where是一个位置,what是一条消息,若cond为假,则输出警告:“ASSERT 失败:where:'what',文件 xyz.cpp,第 234 行”,并退出程序。 - Q_CHECK_PTR(ptr),其中
ptr是一个指针。如果ptr为0,则输出警告“在文件xyz.cpp的第234行:内存不足”,并退出程序。
这些宏有助于检测程序错误,例如如下所示:
char *alloc(int size)
{
Q_ASSERT(size > 0);
char *ptr = new char[size];
Q_CHECK_PTR(ptr);
return ptr;
}Q_ASSERT()、Q_ASSERT_X() 和Q_CHECK_PTR() 在编译时定义了QT_NO_DEBUG 时将展开为空。因此,这些宏的参数不应产生任何副作用。以下是Q_CHECK_PTR() 的错误用法:
char *alloc(int size)
{
char *ptr;
Q_CHECK_PTR(ptr = new char[size]); // WRONG
return ptr;
}如果在此代码编译时定义了 `QT_NO_DEBUG `,则 `Q_CHECK_PTR()` 表达式中的代码将不会被执行,且`alloc`会返回一个未初始化的指针。
Qt 库包含数百项内部检查,当检测到编程错误时会打印警告消息。因此,我们建议您在开发基于 Qt 的软件时使用 Qt 的调试版本。
在QML 中也可以进行日志记录和categorized logging 。
常见错误
有一个错误非常常见,值得在此提及:如果您在类声明中包含Q_OBJECT 宏并运行Meta-Object Compiler(moc ),但忘记将moc 生成的对象代码链接到可执行文件中,您将收到非常令人困惑的错误信息。 任何抱怨缺少vtbl 、_vtbl 、__vtbl 或类似文件的链接错误,很可能都是由这个问题引起的。
© 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.