查看导致致命异常的原因(事后分析)使用WinDbg的C++应用程序

xzlaal3s  于 2022-11-19  发布在  其他
关注(0)|答案(3)|浏览(170)

情况:

使用Visual Studio 2022开发的C++应用程序只有在调试器被分离时才会在发布模式下死亡。现在,虽然我可能知道可能发生这种情况的典型场景,但代码库太大,我无法进行任何逐行代码审查。因此,我将Windbg设置为事后调试器,希望找到它死亡的地方。
现在,请给我点启发。

问题

如何查看引发致命异常的确切原因?有没有办法浏览最近的异常?

讨论

有趣的是,这个多线程应用程序WinDbg在事后分析模式下启动时捕获异常后..应用程序继续运行...我需要暂停执行...因此我想知道是什么引发了异常...以及为什么应用程序在被WindDBG捕获后继续执行代码(如果没有将WindDBG设置为事后调试器,因此没有捕捉到异常,应用程序就会完全停止运行)。

更新日期:

WinDbg在调用后显示的唯一可疑的内容是:
警告:正在继续无法继续的例外状况

gg58donl

gg58donl1#

线程问题是bug修复程序存在的祸根!特别是当你不能连接调试器的时候;
您将不得不求助于生成一个调试版本,并进行额外的日志记录-我喜欢称之为printf() debugging
你提到附加WindDBG -你有一个堆栈跟踪,你可以从它开始工作吗?使用这个作为你的起点,并抛出大量的std::printf行,转储适当的变量,看看你如何从那里去。

wgmfuz8q

wgmfuz8q2#

不管出于什么原因,我的Visual Studio 2022在发布模式下继续生成DEBUG预处理器指令。
另一方面,这会导致setThreadName()调用在发布模式下被编译为二进制**。**
当然,这会引发一个异常--无论出于什么原因,当使用默认配置时,该异常在WinDbg中并不清晰可见。
现在,我感谢@LexLi为我指明了在非侵入模式下使用WinDbg的正确方向。
只有在非侵入模式下,我才能看到正确的堆栈帧,从而能够注意到真正触发异常的原因。
因此,在我的回答中,我将重点介绍如何使WindDbg能够在非侵入模式下(默认为侵入模式)充当事后调试器,因为没有简单切实的方法来改变这一点。
1.首先使WinDbg充当默认的实时事后分析调试器。要实现这一点,请以管理员身份执行windbg -I
1.现在,启动Regedit并前往:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AeDebug
1.编辑Debugger值并添加一个参数-pv,因此在我的示例中,该值最终为:
"C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\windbg.exe" -pv -p %ld -e %ld -g

xuo3flqw

xuo3flqw3#

首先:为什么调试器要改变行为呢?当然,这是不可取的,但你对此无能为力。
1.在调试器下启动的C++应用程序使用不同的内存布局。因此,缓冲区溢出或下溢可能会更改受影响的其他变量。这是UB,因此任何事情都可能发生,并且任何事情都可能随着内存布局而更改。“Appearing to success”是UB的有效形式。
1.调试器为异常处理注册自己。这可能会对计时产生很大影响。特别是在多线程环境中,添加调试器可能会改变一些事情。(按照另一个答案中的建议添加printf语句也可能会改变计时)
部分缓解措施包括:
1.在运行应用程序之后附加调试器。这将给予未修改的CRT内存布局。
1.按照您自己的建议,以非侵入性模式附加调试器可能会。
完全缓解,恕我直言:
当应用程序停止运行时,让Windows使用WER LocalDumps(要求:您没有未处理的异常处理程序)。
这样,您就可以获得一个崩溃转储文件(.DMP),以便以后进行分析。您可以将其发送给其他人以帮助您。

相关问题