Qt记录|Qt+WinDbg分析程序崩溃原因


文章目录

  • 前言
  • 一、dmp文件如何生成?
    • 1.自定义异常捕获入口函数
    • 2.生成pdb文件
    • 3.测试程序
  • 二、利用winDbg进行分析
    • 1.打开工具并配置相关信息
    • 2.开始分析
  • 总结

前言 程序开发免不了产生错误,其中最头疼的当属程序莫名其妙的崩溃,而且你还不知道具体原因。若是在开发阶段还好,自己可以debug一步步调试,但是一旦发布了,就没那么容易定位了。那么这个时候,就需要查看程序运行的log来查询了,当然还有一种就是在程序崩溃前弹出一个窗口,生成对应的dmp文件,帮助定位崩溃原因。 。 提示:以下是本篇文章正文内容,下面案例可供参考
一、dmp文件如何生成? 1.自定义异常捕获入口函数 下面是一个例子,可以参考下,至于dmp文件的生成路径可以指定,我这里就测试下。异常信息都在EXCEPTION_RECORD这个结构体中,如下:
typedef struct _EXCEPTION_RECORD { DWORDExceptionCode; DWORD ExceptionFlags; struct _EXCEPTION_RECORD *ExceptionRecord; PVOID ExceptionAddress; DWORD NumberParameters; ULONG_PTR ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS]; } EXCEPTION_RECORD;

其中ExceptionRecord就是错误代码了,通过这个我们可以大致知道是由于什么原因导致程序崩溃的,最常见的有比如数组越界,空指针异常,除0错误等等,具体的错误可以参考这篇博文,很详细:点击此处
LONG ApplicationCrashHandler(EXCEPTION_POINTERS *pException){//程式异常捕获 qDebug()<<"触发异常!"; HANDLE hDumpFile = CreateFile(TEXT("aaaa.dmp"), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if( hDumpFile != INVALID_HANDLE_VALUE){ //Dump信息 MINIDUMP_EXCEPTION_INFORMATION dumpInfo; dumpInfo.ExceptionPointers = pException; dumpInfo.ThreadId = GetCurrentThreadId(); dumpInfo.ClientPointers = TRUE; //写入Dump文件内容 MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hDumpFile, MiniDumpNormal, &dumpInfo, NULL, NULL); } //这里弹出一个错误对话框并退出程序 EXCEPTION_RECORD* record = pException->ExceptionRecord; QString errCode(QString::number(record->ExceptionCode,16)),errAdr(QString::number((uint)record->ExceptionAddress,16)); QMessageBox::critical(NULL,"程式崩溃","对于发生的错误,表示诚挚的歉意
"+ QString("错误代码:%1错误地址:%2
").arg(errCode).arg(errAdr), QMessageBox::Ok); return EXCEPTION_EXECUTE_HANDLER; }

此处除了生成崩溃是的dump文件外,还利用QMsssageBox弹出窗口用于提示一些有用的信息。然后我们进行注册:
int main(int argc, char *argv[]) { QApplication a(argc, argv); //注冊异常捕获函数 SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER)ApplicationCrashHandler); MainWindow w; w.show(); return a.exec(); }

2.生成pdb文件 我们在debug模式下会用用到pdb文件来调试,那么我们发布的release版本程序如何生成pdb文件呢,由于本人用Qt的编辑器Qtcreator,那我就说下Qt的方法。我们只需要在Qt程序的pro文件中加入以下配置然后重新构建即可:
QMAKE_CXXFLAGS_RELEASE = $$QMAKE_CFLAGS_RELEASE_WITH_DEBUGINFO QMAKE_LFLAGS_RELEASE = $$QMAKE_LFLAGS_RELEASE_WITH_DEBUGINFO

3.测试程序 为了测试是否会生成对应的dmp文件,我们可以写一些简单的代码进行模拟,让程序崩溃。新建一个Qt工程,界面上放一个按钮,简单模拟下越界访问,在槽函数里面做如下操作:
QStringList lit={"1","2","3"}; qDebug()<

重新构建程序,然后点击界面按钮,此处你的程序会崩溃,并且弹出了提示框,这时我们检查程序目录,我这里生成了对应的dmp文件以及pdb文件:
Qt记录|Qt+WinDbg分析程序崩溃原因
文章图片

Qt记录|Qt+WinDbg分析程序崩溃原因
文章图片

二、利用winDbg进行分析 1.打开工具并配置相关信息 首先我们找到windbg工具,我这里是X64版本,不知道在哪的可以在这里搜索,博主我也不知道,都是从小白一步步走来的。。
Qt记录|Qt+WinDbg分析程序崩溃原因
文章图片
Qt记录|Qt+WinDbg分析程序崩溃原因
文章图片
symbol file path(符号文件路径)
source file path(源文件路径)
Image File path(可执行文件路径)

说明一下,关于符号文件路径,如果你的电脑之前没有用过windbg调试,是没有的,我在这个问题上也是踩着坑的。此处路径设置为c:/mysymbol下,后面是一个微软的下载链接,如果找不到就会下载响应的符号文件。
SRVc:\mysymbol http://msdl.microsoft.com/download/symbols;
然后添加pdb文件的路径,根据自己路径修改,我这边设置如下:
Qt记录|Qt+WinDbg分析程序崩溃原因
文章图片
另外两个就不说了,自己设置下。。(偷个懒)
2.开始分析 输入如下命令:
!analyze -v

windbg工具就开始分析了,这个过程时间稍微有点长。。等待之后,打印出来了相关的堆栈信息,最上面是崩溃的地方,通过如下的信息,我们很容易发现程序崩溃的原因,就是在MainWindow的on_pushButton_clicked这个按钮的槽函数里面,后面的是偏移地址
Qt记录|Qt+WinDbg分析程序崩溃原因
文章图片

那么看到这里,可能有的同学就要问了,我们能不能得知崩溃的地方具体在什么地方,哪个文件哪一行。答案是肯定的,windbg这个工具确实强大,在界面上方有一行工具栏,找到调用堆栈,然后点击source,然后在主命令窗口下面继续输入:.excr ,然后堆栈窗口就可以看到具体的信息,如下图所示:
Qt记录|Qt+WinDbg分析程序崩溃原因
文章图片
shadowTest!MainWindow::on_pushButton_clicked+0x12e [f:\qtproject\shadowtest\mainwindow.cpp @ 189]
我们可以看到,问题就在mainwindow.cpp这个文件的第189行,我们可以去查看源码:
【Qt记录|Qt+WinDbg分析程序崩溃原因】Qt记录|Qt+WinDbg分析程序崩溃原因
文章图片
当然,如何你前面设置了源码路径并且打开了源文件,那么点击此处也是会直接跳转到所在行的。好了至此问题已经可以定位到了,之后就可以修改bug。当然windbg还有更多功能,以及各种命令,比如查看堆栈,跳转到栈顶,切换线程,查看变量值等等,有兴趣的小伙伴可以继续深入研究。
总结 本文仅仅简单介绍了windbg这个工具的使用,以及如何去定位程序问题。博主也是慢慢摸索的,如文中有不妥或者错误的地方,欢迎指正,大家共同交流学习。 如需转载,请注明出处。

    推荐阅读