提示:以下是本篇文章正文内容,下面案例可供参考
下面是一个例子,可以参考下,至于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();
}
我们在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
为了测试是否会生成对应的dmp文件,我们可以写一些简单的代码进行模拟,让程序崩溃。新建一个Qt工程,界面上放一个按钮,简单模拟下越界访问,在槽函数里面做如下操作:
QStringList lit={"1","2","3"};
qDebug()<<lit.at(5);
重新构建程序,然后点击界面按钮,此处你的程序会崩溃,并且弹出了提示框,这时我们检查程序目录,我这里生成了对应的dmp文件以及pdb文件:
首先我们找到windbg工具,我这里是X64版本,不知道在哪的可以在这里搜索,博主我也不知道,都是从小白一步步走来的。。
symbol file path(符号文件路径)
source file path(源文件路径)
Image File path(可执行文件路径)
说明一下,关于符号文件路径,如果你的电脑之前没有用过windbg调试,是没有的,我在这个问题上也是踩着坑的。此处路径设置为c:/mysymbol下,后面是一个微软的下载链接,如果找不到就会下载响应的符号文件。
SRVc:\mysymbol http://msdl.microsoft.com/download/symbols;
然后添加pdb文件的路径,根据自己路径修改,我这边设置如下:
另外两个就不说了,自己设置下。。(偷个懒)
输入如下命令:
!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行,我们可以去查看源码:
当然,如何你前面设置了源码路径并且打开了源文件,那么点击此处也是会直接跳转到所在行的。好了至此问题已经可以定位到了,之后就可以修改bug。当然windbg还有更多功能,以及各种命令,比如查看堆栈,跳转到栈顶,切换线程,查看变量值等等,有兴趣的小伙伴可以继续深入研究。