文章目录
- 前言
- 一、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文件:
文章图片
文章图片
二、利用winDbg进行分析 1.打开工具并配置相关信息 首先我们找到windbg工具,我这里是X64版本,不知道在哪的可以在这里搜索,博主我也不知道,都是从小白一步步走来的。。
文章图片
文章图片
symbol file path(符号文件路径)
source file path(源文件路径)
Image File path(可执行文件路径)
说明一下,关于符号文件路径,如果你的电脑之前没有用过windbg调试,是没有的,我在这个问题上也是踩着坑的。此处路径设置为c:/mysymbol下,后面是一个微软的下载链接,如果找不到就会下载响应的符号文件。
SRVc:\mysymbol http://msdl.microsoft.com/download/symbols;然后添加pdb文件的路径,根据自己路径修改,我这边设置如下:
文章图片
另外两个就不说了,自己设置下。。(偷个懒)
2.开始分析 输入如下命令:
!analyze -v
windbg工具就开始分析了,这个过程时间稍微有点长。。等待之后,打印出来了相关的堆栈信息,最上面是崩溃的地方,通过如下的信息,我们很容易发现程序崩溃的原因,就是在MainWindow的on_pushButton_clicked这个按钮的槽函数里面,后面的是偏移地址
文章图片
那么看到这里,可能有的同学就要问了,我们能不能得知崩溃的地方具体在什么地方,哪个文件哪一行。答案是肯定的,windbg这个工具确实强大,在界面上方有一行工具栏,找到调用堆栈,然后点击source,然后在主命令窗口下面继续输入:.excr ,然后堆栈窗口就可以看到具体的信息,如下图所示:
文章图片
shadowTest!MainWindow::on_pushButton_clicked+0x12e [f:\qtproject\shadowtest\mainwindow.cpp @ 189]
我们可以看到,问题就在mainwindow.cpp这个文件的第189行,我们可以去查看源码:
【Qt记录|Qt+WinDbg分析程序崩溃原因】
文章图片
当然,如何你前面设置了源码路径并且打开了源文件,那么点击此处也是会直接跳转到所在行的。好了至此问题已经可以定位到了,之后就可以修改bug。当然windbg还有更多功能,以及各种命令,比如查看堆栈,跳转到栈顶,切换线程,查看变量值等等,有兴趣的小伙伴可以继续深入研究。
总结 本文仅仅简单介绍了windbg这个工具的使用,以及如何去定位程序问题。博主也是慢慢摸索的,如文中有不妥或者错误的地方,欢迎指正,大家共同交流学习。 如需转载,请注明出处。
推荐阅读
- c++|程序员怎么提高代码编写的速度()
- QT学习|QXlsx读写Excel表格
- Qt|QtXlsx 读写 excel
- c语言|每天一练——牛客网基础语法(10)
- 纯C详解数据结构|详解线性表——顺序表【一看完,诶,发现我已经掌握顺序表核心了】
- #|图的邻接矩阵(广度优先遍历)
- 我犯下的错误|错误(对不同类型变量定义相同变量名)
- #|邻接矩阵(有向图顶点的入度)
- #|对简单字符串的排序整理(简单的2种方法)