Qt Creator不能在抛出异常时中断(使用CDB作为调试器)

3
我将Qt Creator设置为在C++异常被抛出时中断

enter image description here

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

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

但是它没有在throw std::runtime_error("error");处中断。我正在使用CDB,而不是GDB,因为我正在使用MSVC Kit

编辑: 这里还有另一个问题,CDB对于该OP虽然速度较慢,但仍能正常工作。所以原则上应该可以工作。我的配置是:Qt Creator 3.3.0,使用Qt4/MSVC 9.0(x86)进行编译,调试器是CDB 6.2.9200.16384。

编辑2: 这是我在CDB日志窗口中收到的内容(我在带有断点和不带断点的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在评论中解释了为什么它失败:

请记住,您正在使用非常旧的MSVC ++版本,VS2012进行了重大更改。 pastebin显示它与__CxxThrowException @ 8(MSVCR90D.dll)包含的DLL非常不同步,在抛出异常之前从未到达该DLL。使用sxe调试器命令很简单,任何异常抛出时都会自动中断..也许您根本不应该使用QT的UI,它看起来太笨重了。- Hans Passant 10小时前

只需查看跟踪,调试器就会显示它正在搜索哪些DLL以获取“CxxThrowException”。它永远不会到达msvcr90d.dll。而异常是在搜索符号后抛出的,此后一切都结束了。完全不同步。- Hans Passant 56分钟前


你确定它在CDB上得到支持了吗? - Ethouris
好的,只是一个简单的陈述,关于Qt Creator是否支持CDB的这个功能。如果需要调试器实现该功能,则可能两者都需要。 - Ethouris
我刚刚发现了这个链接 - https://stackoverflow.com/questions/24553842/breakpoint-break-when-c-exception-is-thrown-why-so-slow,它虽然有点慢,但至少对于这个人的设置是有效的。因此,CDB和Qt Creator都应该支持这个功能。不过我不知道为什么在我的电脑上无法使用。 - sashoalm
1
请注意,您正在使用非常旧的MSVC++版本,VS2012有很大的变化。Pastebin显示它与__CxxThrowException@8(MSVCR90D.dll)包含的DLL非常不同步,在抛出异常之前从未到达该DLL。使用sxe调试器命令很简单,当抛出任何异常时自动中断。也许您根本不应该使用QT的UI,它看起来太过陈旧。 - Hans Passant
1
只需查看跟踪,调试器会显示它正在搜索哪些DLL文件中的“CxxThrowException”。 它从未到达msvcr90d.dll。 而异常是在搜索符号时抛出的,之后一切都结束了。 完全不同步。 - Hans Passant
显示剩余8条评论
1个回答

1
我将简要说明为什么出现了问题,找到一个解决方法将会很困难。您的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帮助文件中没有看到任何内容,但它可能已经有一段时间没有更新了。谷歌也没有帮助。我建议您提出一个相关问题。最重要的是,您的版本号存在相当大的不匹配。您使用的编译器是2008年的老版本,调试器是相当新的SDK 8.0版本,我无法确定您使用的QT版本。
因此,一个可能的解决方法是故意使用旧版本的CDB,这个版本更有可能被与您使用的QT前端版本一起测试。下载相应的SDK版本,版本6.0匹配VS2008时间框架。我认为“Windows调试工具”当时仍然是一个单独的下载,而不是包含在SDK中。另一个解决方法是停止依赖友好的QT前端,并学会从命令提示符驱动CDB。WINDBG比较实用,使用相同的调试引擎但具有GUI界面。只是比较实用,仍然大多数是提示驱动。您将失去几天时间来学习命令。使用sxe命令使调试器在抛出异常时中断非常简单。

Pdb确实存在于c:\Users\sasho\AppData\Local\Temp\symbolcache\msvcr90d.i386.pdb\269DF420EA5F4A06B5C84447F4A0C7F71\msvcr90d.i386.pdb - sashoalm
我尝试使用CDB 6.12,但它仍然无法在异常情况下中断。不过,它不再显示“DLL中的未经授权符号”。我已将日志上传到http://pastebin.com/JLkYi5iJ。 - sashoalm
不错的尝试,但是问题完全相同,它仍然过早地发出了“g”命令。这似乎非常糟糕,显然没有人这样做。VS调试器非常出色,所以这并不奇怪。为什么不使用它呢? - Hans Passant
有时我会使用VS进行调试,当我需要调试抛出的异常时,我最终使用了它。通常在Qt Creator调试中遇到一些错误(或缺少功能)时也会使用它。还有一些关于监视变量的内容。似乎CDB的支持比GDB少。 - sashoalm

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接