Qt Creator 无法中断抛出的异常(使用 CDB 作为调试器时)

Qt Creator can't break on thrown exceptions (when using CDB as debugger)

我将 Qt Creator 设置为 break when a C++ exception is thrown:

然后我用这段代码测试了它:

try {
    throw std::runtime_error("error");
} catch (std::exception &e) {
    qDebug("%s", e.what());
}

但它并没有在 throw std::runtime_error("error"); 上中断。我使用的是 CDB,而不是 GDB,

编辑:another question where CDB is working for the OP,虽然慢。所以它应该在原则上工作。我的配置是:Qt Creator 3.3.0,用Qt4/MSVC9.0(x86)编译,调试器是CDB 6.2.9200.16384.

编辑 2: 这就是我在 CDB 日志中得到的内容 window(我在有断点和没有断点的 CDB 日志之间做了一个区别):

<bu100400 CxxThrowException
<!qtcreatorcdbext.breakpoints -t 1 -v
<!qtcreatorcdbext.pid -t 2
dATTEMPT SYNC
d*** Bp expression 'CxxThrowException' contains symbols not qualified with module name.
 1 breakpoint(s) pending...
 *** Unable to resolve unqualified symbol in Bp expression 'CxxThrowException' from module 'C:\Windows\WinSxS\x86_microsoft.windows.common-controls_6595b64144ccf1df_5.82.7601.18201_none_ec80f00e8593ece5\comctl32.dll'.

完整的 CDB 日志(以备不时之需):http://pastebin.com/jhNRy9bE

编辑 3: @HansPassant 在评论中解释了失败的原因:

Keep in mind that you are using a very old version of MSVC++, big changes at VS2012. The pastebin shows it being out of sync pretty badly, never getting to the DLL that contains __CxxThrowException@8 (MSVCR90D.dll) before the exception is thrown. It is simple with the sxe debugger command, automatic break when any exception is thrown.. Maybe you shouldn't be using QT's UI at all, it looks too gimpy. – Hans Passant 10 hours ago

Just look at the trace, the debugger shows what DLLs it is searching for "CxxThrowException". It never gets to msvcr90d.dll. And the exception is thrown while it is searching for the symbol after which it all ends. Completely out of sync. – Hans Passant 56 mins ago

我会写下为什么会出错,很难找到解决方法。您的 pastebin 中的调试器跟踪说明了这个故事。

基本问题是调试器和QT前端之间的通信比较差。在您的情况下,它不同步,QT 等待调试器完成命令的时间不够长。 QT 尝试在 msvcr90d.dll!__CxxThrowException@8 函数上设置断点,该函数在 Microsoft CRT 中引发 C++ 异常。如果程序使用多个 CRT,则此函数可以出现在多个可执行文件中。一个很常见的事故,由使用 /MT 构建引起。如果您使用通过 COM 与之交互的隔离良好的 DLL,有时是故意的。

正如您想象的那样,这需要一段时间,链接问题中的抱怨,调试器必须为加载的每个 DLL 仔细检查符号信息。如果 DLL 的 PDB 需要从符号服务器下载并且没有缓存以便下次调试时可用,则将花费特别长的时间。不是你的问题,它确实将缓存位置设置为 C:\Users\sasho\AppData\Local\Temp\symbolcache。去看看,确认您确实在那里看到了操作系统 DLL 的 PDB。

这个操作很棘手,调试器没有给出一个良好的信号来表明它已完成对 DLL 的搜索。 QT 应该 做的是根据它获得的 DLL 列表验证调试器反馈。它不会那样做,它会在调试器完成搜索之前发出 g 命令。可能是超时时间太短,但实际上 QT 并不指望调试器在后台执行此命令。对人类的便利,在这里并不是很有帮助 :)

应该有一种方法可以将 CDB 配置为不在后台执行此搜索。这隐藏得很好,我在 debugger.chm 帮助文件中没有看到任何内容,但它可能有一段时间没有更新了。 Google 也无济于事。我建议你问一个关于它的问题。最重要的可能是您的版本号有相当大的不匹配。你用的编译器是2008 vintage,调试器很新,SDK 8.0版本,不知道你用的是什么QT版本

因此,一种可能的解决方法是有意使用较旧版本的 CDB,该版本更有可能使用您使用的 QT 前端版本进行过测试。下载对应的SDK版本,6.0版本匹配VS2008时间段。我 认为 "Debugging Tools for Windows" 当时仍然是一个单独的下载,尚未包含在 SDK 中。另一个解决方法是停止依赖友好的 QT 前端并学习从命令提示符驱动 CDB。 WINDBG 更有用,它使用相同的调试引擎但具有 GUI 界面。适度,它仍然主要是提示驱动。但是,您确实会浪费几天学习这些命令的时间。让调试器在抛出异常时中断是微不足道的,使用 sxe 命令。