Qt 生成dump文件及windbg调试(进阶版)

一、异常捕获和dump文件生成

直接参考如下:
main.cpp

  1 #include "mainwindow.h"
  2 #include <QApplication>
  3 #include <Windows.h>
  4 #include "Login/logindlg.h"
  5 #include <DbgHelp.h>
  6 #include <tchar.h>
  7 #include <qt_windows.h>
  8 #pragma comment(lib, "user32.lib")
  9 #pragma comment(lib, "dbghelp.lib")
 10 
 11 
 12 void GetExceptionDescription(DWORD errCode,QString& err)
 13 {
 14 #if 0
 15 
 16 
 17 #else
 18 //    errCode = 0xc0000005;
 19     LPTSTR lpMsgBuf = NULL;
 20     HMODULE Hand = LoadLibrary(TEXT("ntdll.dll"));
 21     FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
 22                   FORMAT_MESSAGE_IGNORE_INSERTS/*FORMAT_MESSAGE_FROM_SYSTEM*/|
 23                   FORMAT_MESSAGE_FROM_HMODULE,
 24                   Hand,
 25                   errCode,
 26                   MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT),
 27                   (LPTSTR)&lpMsgBuf,
 28                   0,NULL);
 29     err = QString::fromWCharArray( lpMsgBuf );
 30     qDebug()<<err;
 31     LocalFree(lpMsgBuf);
 32 #endif
 33 }
 34 
 35 
 36 LONG ApplicationCrashHandler(EXCEPTION_POINTERS *pException){//程式异常捕获
 37     /*
 38       ***保存数据代码***
 39     */
 40     //创建 Dump 文件
 41     qDebug()<<"触发异常!";
 42     QString createPath = QCoreApplication::applicationDirPath()+"/Dumps";
 43     QDir dir;
 44     dir.mkpath(createPath);
 45     createPath=QString("%1/dump_%2.dmp").arg(createPath).arg(QDateTime::currentDateTime().toString("yyyy_MM_dd_hh_mm_ss_zzz"));
 46     std::wstring wlpstr = createPath.toStdWString();
 47     LPCWSTR lpcwStr = wlpstr.c_str();
 48 
 49     HANDLE hDumpFile = CreateFile(lpcwStr,
 50                                   GENERIC_WRITE,
 51                                   0,
 52                                   NULL,
 53                                   CREATE_ALWAYS,
 54                                   FILE_ATTRIBUTE_NORMAL,
 55                                   NULL);
 56     if( hDumpFile != INVALID_HANDLE_VALUE){
 57         //Dump信息
 58         MINIDUMP_EXCEPTION_INFORMATION dumpInfo;
 59         dumpInfo.ExceptionPointers = pException;
 60         dumpInfo.ThreadId = GetCurrentThreadId();
 61         dumpInfo.ClientPointers = FALSE;
 62         //写入Dump文件内容
 63         MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hDumpFile, MiniDumpNormal, &dumpInfo, NULL, NULL);
 64     }
 65     //这里弹出一个错误对话框并退出程序
 66     EXCEPTION_RECORD* record = pException->ExceptionRecord;
 67     QString errCode(QString::number(record->ExceptionCode,16)),errAdr(QString::number((UINT)((UINT_PTR)record->ExceptionAddress),16));;
 68     QString errstr;
 69     GetExceptionDescription(record->ExceptionCode,errstr);
 70     if(record->NumberParameters>0){
 71         if(record->ExceptionInformation[0]==0){
 72             errstr+="\r\n访问冲突,线程试图读取不可访问的数据";
 73         }else if(record->ExceptionInformation[0]==1){
 74             errstr+="\r\n访问冲突,线程尝试写入不可访问的地址";
 75         }
 76     }
 77     QMessageBox::critical(NULL,"程式崩溃","<FONT size=4><div><b>程式崩溃</b><br/></div>"+
 78         QString("<div>错误代码:%1</div><div>错误地址:%2</div><div>具体原因:%3</div></FONT>").arg(errCode).arg(errAdr).arg(errstr),
 79         QMessageBox::Ok);
 80     return EXCEPTION_EXECUTE_HANDLER;
 81 }
 82 
 83 int main(int argc, char *argv[])
 84 {
 85     QApplication a(argc, argv);
 86     SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER)ApplicationCrashHandler);//注冊异常捕获函数
 87     //唯一性检测
 88     QSharedMemory singleton(a.applicationName());
 89     if(!singleton.create(1))  {    //已经存在的
 90         QMessageBox::critical(nullptr, QObject::tr("错误"),
 91                               QObject::tr("程序已经在运行,请先关闭!"));
 92         return -1;
 93     }
 94     LoginDlg pLdlg;
 95     MainWindow w;
 96     QObject::connect(&pLdlg,&LoginDlg::sig_sendCurrentLoginUser,&w,&MainWindow::slot_setCurrentLoginUser);
 97     if(pLdlg.exec()==QDialog::Accepted){
 98         w.show();
 99 #if 0
100         return a.exec();
101 #else
102         int ret = a.exec();
103         if (ret == 773) {
104              singleton.detach();
105              QProcess::startDetached(qApp->applicationFilePath(), QStringList());
106              return 0;
107          }
108          return ret;
109 #endif
110     }else{
111         return -1;
112     }
113 }

根据异常代码获取错误描述的函数,自定义的。

本文福利,费领取Qt开发学习资料包、技术视频,内容包括(C++语言基础,Qt编程入门,QT信号与槽机制,QT界面开发-图像绘制,QT网络,QT数据库编程,QT项目实战,QSS,OpenCV,Quick模块,面试题等等)↓↓↓↓↓↓见下面↓↓文章底部点击费领取↓↓

1 void GetExceptionDescription(DWORD errCode,QString& err)

异常捕获回调函数,windows系统固定参数的,关于EXCEPTION_POINTERS 异常结果,可以查看MSDN官方文档,有详细的介绍。

1 LONG ApplicationCrashHandler(EXCEPTION_POINTERS *pException)

里面用到了唯一性检测(只能打开一个exe程序),以及自动重启的相关代码,需要的可以参考(白嫖…)

二、调试

1.安装Windbg Preview

目前已知该软件唯一安装途径好像只有微软商店,反正博主是从微软商店下载的

 

2.调试

先手动制造一个异常吧,就0x0000005常见的吧,内存访问冲突,或者你弄一个除0的也可以,然后会在程序当前目录的Dump文件夹下生成一个异常的mini dump文件,如下图:

 

异常文件:

 

打开刚才安装的windbg preview,设置一下符号缓存文件路径,以及你自己程序的pdb文件路径,友情提示,Qt在release模式下生成pdb文件需要在pro文件增加如下配置:

1 QMAKE_CXXFLAGS_RELEASE += $$QMAKE_CFLAGS_RELEASE_WITH_DEBUGINFO
2 QMAKE_LFLAGS_RELEASE += $$QMAKE_LFLAGS_RELEASE_WITH_DEBUGINFO

好了,继续我们的调试,配置如下

 配置完成之后,将刚才生成的pdb文件拖入command窗口,然后点击自动分析:

此时会处于BUSY状态,从微软服务器下载各种符号文件,等他完成。

 之后,可以看到调用堆栈信息,以及错误代码。094(除0错误),因为之前赋值为0了,==改成=了。

1     if(mGridLines=0) mGridLines=1;
2     if(mGridColumns=0) mGridColumns=1;

所以后续调用就出现除0的问题,可以直接看到红色框内,源码第61行有问题,感觉比windows自带的windbg强大太多了。

另外还有个问题,就是通过FormatMessage获取错误码对应的描述的时候,访问冲突会出现如下描述:“0x%p 指令引用了 0x%p 内存。该内存不能为 %s。\r\n”,占位符的参数是否需要通过FormatMessage的最后一个参数va_list传递进去,或者说有其他的方案,能完整显示出具体指令和内存地址,目前还没有解决,虚心请教各位大佬,不胜感激。

总结
提示:这里对文章进行总结:
例如:以上就是今天要讲的内容,本文仅仅简单介绍了windbg preview的使用以及异常捕获dump文件的调试。

本文福利,费领取Qt开发学习资料包、技术视频,内容包括(C++语言基础,Qt编程入门,QT信号与槽机制,QT界面开发-图像绘制,QT网络,QT数据库编程,QT项目实战,QSS,OpenCV,Quick模块,面试题等等)↓↓↓↓↓↓见下面↓↓文章底部点击费领取↓↓

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值