Qt+WinDbg分析程序崩溃原因

文章目录

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


前言

程序开发免不了产生错误,其中最头疼的当属程序莫名其妙的崩溃,而且你还不知道具体原因。若是在开发阶段还好,自己可以debug一步步调试,但是一旦发布了,就没那么容易定位了。那么这个时候,就需要查看程序运行的log来查询了,当然还有一种就是在程序崩溃前弹出一个窗口,生成对应的dmp文件,帮助定位崩溃原因。 。

提示:以下是本篇文章正文内容,下面案例可供参考

一、dmp文件如何生成?

1.自定义异常捕获入口函数

下面是一个例子,可以参考下,至于dmp文件的生成路径可以指定,我这里就测试下。异常信息都在EXCEPTION_RECORD这个结构体中,如下:

typedef struct _EXCEPTION_RECORD {
    DWORD    ExceptionCode;
    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()<<lit.at(5);

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

二、利用winDbg进行分析

1.打开工具并配置相关信息

首先我们找到windbg工具,我这里是X64版本,不知道在哪的可以在这里搜索,博主我也不知道,都是从小白一步步走来的。。
Qt+WinDbg分析程序崩溃原因_第2张图片Qt+WinDbg分析程序崩溃原因_第3张图片symbol file path(符号文件路径)
source file path(源文件路径)
Image File path(可执行文件路径)

说明一下,关于符号文件路径,如果你的电脑之前没有用过windbg调试,是没有的,我在这个问题上也是踩着坑的。此处路径设置为c:/mysymbol下,后面是一个微软的下载链接,如果找不到就会下载响应的符号文件。

SRVc:\mysymbol http://msdl.microsoft.com/download/symbols;

然后添加pdb文件的路径,根据自己路径修改,我这边设置如下:
Qt+WinDbg分析程序崩溃原因_第4张图片另外两个就不说了,自己设置下。。(偷个懒)

2.开始分析

输入如下命令:

!analyze -v

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

Qt+WinDbg分析程序崩溃原因_第5张图片
那么看到这里,可能有的同学就要问了,我们能不能得知崩溃的地方具体在什么地方,哪个文件哪一行。答案是肯定的,windbg这个工具确实强大,在界面上方有一行工具栏,找到调用堆栈,然后点击source,然后在主命令窗口下面继续输入:.excr ,然后堆栈窗口就可以看到具体的信息,如下图所示:
Qt+WinDbg分析程序崩溃原因_第6张图片shadowTest!MainWindow::on_pushButton_clicked+0x12e [f:\qtproject\shadowtest\mainwindow.cpp @ 189]

我们可以看到,问题就在mainwindow.cpp这个文件的第189行,我们可以去查看源码:

在这里插入图片描述当然,如何你前面设置了源码路径并且打开了源文件,那么点击此处也是会直接跳转到所在行的。好了至此问题已经可以定位到了,之后就可以修改bug。当然windbg还有更多功能,以及各种命令,比如查看堆栈,跳转到栈顶,切换线程,查看变量值等等,有兴趣的小伙伴可以继续深入研究。


总结

本文仅仅简单介绍了windbg这个工具的使用,以及如何去定位程序问题。博主也是慢慢摸索的,如文中有不妥或者错误的地方,欢迎指正,大家共同交流学习。 如需转载,请注明出处。

你可能感兴趣的:(Qt记录,qt,c++)