在前一篇文章中,我们介绍了单线程场景下crash分析步骤和基本思路。但在实际项目中,往往是多线程或者更复杂的情况,此时通过!analyze -v命令难以直接找到出问题的点。
以下代码演示了多线程场景下的crash分析过程,需要特别注意的是,我们的工程需要禁用优化,否则分析问题不直观。如下所示:
示例代码
多线程场景异常示例代码:
#include "utilityAPI.h"
#include <string>
#pragma comment(lib, "utility.lib")
typedef struct
{
char szName[128];
char szAddr[128];
unsigned usAge;
}STRU_STUDENT_INFO;
//执行函数参数
void GetStudentInfo(char* name, STRU_STUDENT_INFO *pStudent, int count)
{
printf("student age=%d",pStudent->usAge);
}
//子线程类,其中TTThread为自己封装的线程类
class CMultiThread :public TTThread
{
virtual unsigned int Process();
};
//子线程函数实现
unsigned int CMultiThread::Process()
{
STRU_STUDENT_INFO *pStudent = NULL;
GetStudentInfo("jimmy",pStudent,5);
return 0;
}
int main(int argc, char const *argv[])
{
//子线程
CMultiThread test;
test.Create();
//主线程
for (int i = 0; i < 1000; i++)
{
Sleep(100);
}
return 0;
}
dump分析过程
1、执行 !analyze -v命令
!analyze -v命令会进程大量的内部分析,并给出当前异常的详细信息记录
在此次自动分析结论中,windbg认为异常点位于主线程中45行代码,其错误代码段如下:
很显然,windbg给出的结论并不准确,因此需要进一步确认异常点。
在这个分析报告中我们也没有找到异常上下文地址以及正确的异常记录地址,而这两个信息又是比较重要的。
2、执行~* kbn命令
在之前文章中说过,当软件异常发生时,如果异常没有被捕获,异常信息会经过UnhandledExceptionFilter函数,然后再通知用户。
为了找出该函数,执行~* kbn
命令显示出所有线程的调用栈信息,发现线程1存在未处理的异常点,截图如下:
地址00b8f980为UnhandledExceptionFilter入参,该地址为_EXCEPTION_POINTERS
结构体指针。
3、 dd命令分析
该命令给出了EXCEPTION_POINTERS structure结构体信息,第1个为异常记录点地址和第二个为上下文地址:
0:000> dd 00b8f980 L2
00b8f980 00b8fa80 00b8fa9c
- 00b8fa80 异常记录点地址
- 00b8fa9c上下文地址
4、执行 .exr 和.cxr命令
- .exr (Display Exception Record)
- .cxr (Display Context Record)
执行完.exr 和.cxr命令,windbg会调出执行异常的源码,windbg将光标定位于printf语句.此时可以认为是空指针造成的。下面进行进一步确认。
5、kP命令
此时我们可以k命令显示堆栈信息,这里使用kP命令会显示所有参数信息,kP命令显示了函数调用栈以及函数入参值,如下图:
通过kP命令可以发现,GetStudentInfo函数入参中的pStudent为空指针,结合执行完.cxr 007af90c
命令后,光标指向printf("student age=%d",pStudent->usAge);
语句。
因此可以得出结论:函数崩溃原因是因为访问空指针对象导致的。
总结
在实际项目中,一个应用程序中必然存在多线程的场景,通过windbg自动分析并不能直接定位出程序崩溃点。此时就需要依赖切换实际的出问题的运行上下文才能分析出真正根因。需要注意的是,我们的功能需要禁用优化编译选项,对于启用代码优化的crash分析,大家依照这篇文章自行分析,以便加深印象。
希望这篇文章能够给大家带来实际的帮助,本文参考以下文章:
https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/bug-check-0x1e–kmode-exception-not-handled