Windbg可以看到Visual Studio中看不到的有效函数调用堆栈

目录

1、Visual Studio中看不到有效的函数调用堆栈

2、使用Windbg调试运行主程序,看到了有效的函数调用堆栈

3、根据函数名和行号去查看对应的C++源码,定位问题

4、总结


VC++常用功能开发汇总(专栏文章列表,欢迎订阅,持续更新…)https://blog.csdn.net/chenlycly/article/details/124272585C++软件异常排查从入门到精通系列教程(专栏文章列表,欢迎订阅,持续更新…)https://blog.csdn.net/chenlycly/article/details/125529931       最近遇到一个主程序启动报错的问题,在Visual Studio中启动调试会报出异常,点开call stack函数调用堆栈页面却看不到有效的函数调用堆栈。后来尝试使用Windbg启动主程序进行调试,报出异常时Windbg中却看到了完整的函数调用堆栈。这个问题也正是借助Windbg的动态调试解决的,今天就来分享一下该问题完整的排查分析过程。

1、Visual Studio中看不到有效的函数调用堆栈

       在给新人搭建项目在Debug下的运行调试环境时,先是拷贝了底层各个模块的Debug版本dll库,将项目中需要编译的工程添加到解决方案中进行编译,最后在Visual Studio中启动Debug下主程序的调试,结果主程序还没启动起来就报错了,弹出如下报错提示框:

提示框中显示的错误描述信息为:Access violation executing location 0x00000000,即执行0x00000000地址时产生了访问违例,这个0x00000000是代码段的地址,很有可能是call了这个无效的代码段地址引发的访问违例。

       于是切换到Call Stack函数调用堆栈页面,去查看此时的函数调用堆栈。但并没有看到有效的函数调用堆栈,如下所示:

看不到有效的函数调用堆栈,这个问题就不好分析了。难道是底层的dll库之间不匹配导致的?亦或是Debug版本的dll库与Release版本的dll混用导致的?

2、使用Windbg调试运行主程序,看到了有效的函数调用堆栈

       Visual Studio调试状态下看不到有效的函数调用堆栈,于是想尝试使用Windbg启动主程序调试运行,看看在发生异常时能否看到有效的信息。使用Windbg打开目标主程序开始调试,Windbg确实捕获到了异常,中断了下来。于是输入kn命令,查看到如下的函数调用堆栈:

       Windbg确实很强大啊,Windbg中看到了发生异常时的完整函数调用堆栈。从上图可以看到,异常崩溃发生在mediaxxx.dll模块中。因为没有pdb文件,所以函数调用堆栈中只能看到崩溃发生在mediaxxx.dll模块中,看不到具体的函数名。

       于是输入lm vm mediaxxx*命令去查看mediaxxx.dll文件的时间戳:

该dll库的时间戳为:2022年8月3日15时45分09秒,该时间就是mediaxxx.dll库文件编译生成的时间,按照这个时间点到版本服务器上查找对应时间的pdb文件。取来pdb文件后,将pdb文件的路径添加到Windbg中(在添加页面记得勾选Reload选项),然后重新输入kn,看到了详细的函数名,如下:

看到问题是发生在initgloble函数的553行代码上:

J:\media\media***\source\video\videocom***.cpp @ 553

此外,还能看到该函数位于哪个cpp文件中。

3、根据函数名和行号去查看对应的C++源码,定位问题

      于是将完整的函数调用堆栈发给维护mediaxxx.dll库的同事,根据显示的函数名和行号,去查看C++源码,看看出问题的代码是啥样子的。

       查看到如下的这行代码:

这里的m_pHWDec_Startup变量应该是个函数指针,此处通过该指针中保存的函数地址,去调用对应的函数的。于是搜索给m_pHWDec_Startup指针变量赋值的地方,找到了如下的代码:

根据同事提示,此处是从uniplay.dll库中动态获取PLAYXX_Startup函数地址,赋值给m_pHWDec_Startup函数指针变量的。

       所以,调用uniplay.dll中的接口是通过动态加载库的方式去操作的,很有可能是主程序的路径中缺少uniplay.dll库文件导致PLAYXX_Startup函数获取失败,所以m_pHWDec_Startup函数指针为空,这样代码中去call了这个空指针,所以出现了“Access violation executing location 0x00000000”异常。经查看,主程序的路径中确实是没有uniplay.dll库文件的,手动将该库拷贝到主程序的目录中就没问题了。

4、总结

       在使用Visual Studio等IDE工具调试C++代码的过程中遇到了异常,如果看不到有用的信息或线索,可以尝试使用Windbg等调试工具去动态调试目标程序,看看发生异常时能否看到有用的内容。

       类似的问题,以前我们也遇到过,当代码中发生Stack overflow线程栈溢出时,Visual Studio会直接停止调试,退出调试状态,这样也就看不到异常发生的函数调用堆栈了。但用Windbg动态调试目标进程时发生线程栈溢出,则可以看到完整的函数调用堆栈。本文恰好是另一个实例。

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注