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

文章目录

  • 前言
  • 一、异常捕获和dump文件生成
  • 二、调试
    • 1.安装Windbg Preview
    • 2.调试
  • 总结


前言

至于为什么是进阶版,因为之前也写过一篇,好像是去年的时候,当时博主也是能力有限,菜鸟级别,都是在职场一步步的摸爬滚打,不断的学习和摸索才逐渐成长。好了,废话不多说了,今天给大家分享一个更强大的工具windbg preview。


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

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

还是简单的说一下吧,各位不了解的也可以看看本人的另一篇博客。也可以直接参考如下:
main.cpp

#include "mainwindow.h"
#include 
#include 
#include "Login/logindlg.h"
#include 
#include 
#include 
#pragma comment(lib, "user32.lib")
#pragma comment(lib, "dbghelp.lib")


void GetExceptionDescription(DWORD errCode,QString& err)
{
#if 0


#else
//    errCode = 0xc0000005;
    LPTSTR lpMsgBuf = NULL;
    HMODULE Hand = LoadLibrary(TEXT("ntdll.dll"));
    FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
                  FORMAT_MESSAGE_IGNORE_INSERTS/*FORMAT_MESSAGE_FROM_SYSTEM*/|
                  FORMAT_MESSAGE_FROM_HMODULE,
                  Hand,
                  errCode,
                  MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT),
                  (LPTSTR)&lpMsgBuf,
                  0,NULL);
    err = QString::fromWCharArray( lpMsgBuf );
    qDebug()<<err;
    LocalFree(lpMsgBuf);
#endif
}


LONG ApplicationCrashHandler(EXCEPTION_POINTERS *pException){//程式异常捕获
    /*
      ***保存数据代码***
    */
    //创建 Dump 文件
    qDebug()<<"触发异常!";
    QString createPath = QCoreApplication::applicationDirPath()+"/Dumps";
    QDir dir;
    dir.mkpath(createPath);
    createPath=QString("%1/dump_%2.dmp").arg(createPath).arg(QDateTime::currentDateTime().toString("yyyy_MM_dd_hh_mm_ss_zzz"));
    std::wstring wlpstr = createPath.toStdWString();
    LPCWSTR lpcwStr = wlpstr.c_str();

    HANDLE hDumpFile = CreateFile(lpcwStr,
                                  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 = FALSE;
        //写入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)((UINT_PTR)record->ExceptionAddress),16));;
    QString errstr;
    GetExceptionDescription(record->ExceptionCode,errstr);
    if(record->NumberParameters>0){
        if(record->ExceptionInformation[0]==0){
            errstr+="\r\n访问冲突,线程试图读取不可访问的数据";
        }else if(record->ExceptionInformation[0]==1){
            errstr+="\r\n访问冲突,线程尝试写入不可访问的地址";
        }
    }
    QMessageBox::critical(NULL,"程式崩溃","
程式崩溃
"
+ QString("
错误代码:%1
错误地址:%2
具体原因:%3
").arg(errCode).arg(errAdr).arg(errstr), QMessageBox::Ok); return EXCEPTION_EXECUTE_HANDLER; } int main(int argc, char *argv[]) { QApplication a(argc, argv); SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER)ApplicationCrashHandler);//注冊异常捕获函数 //唯一性检测 QSharedMemory singleton(a.applicationName()); if(!singleton.create(1)) { //已经存在的 QMessageBox::critical(nullptr, QObject::tr("错误"), QObject::tr("程序已经在运行,请先关闭!")); return -1; } LoginDlg pLdlg; MainWindow w; QObject::connect(&pLdlg,&LoginDlg::sig_sendCurrentLoginUser,&w,&MainWindow::slot_setCurrentLoginUser); if(pLdlg.exec()==QDialog::Accepted){ w.show(); #if 0 return a.exec(); #else int ret = a.exec(); if (ret == 773) { singleton.detach(); QProcess::startDetached(qApp->applicationFilePath(), QStringList()); return 0; } return ret; #endif }else{ return -1; } }

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

void GetExceptionDescription(DWORD errCode,QString& err)

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

LONG ApplicationCrashHandler(EXCEPTION_POINTERS *pException)

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

二、调试

1.安装Windbg Preview

目前已知该软件唯一安装途径好像只有微软商店,反正博主是从微软商店下载的
Qt生成dump文件及windbg调试(进阶版)_第1张图片

2.调试

先手动制造一个异常吧,就0x0000005常见的吧,内存访问冲突,或者你弄一个除0的也可以,然后会在程序当前目录的Dump文件夹下生成一个异常的mini dump文件,如下图:
在这里插入图片描述Qt生成dump文件及windbg调试(进阶版)_第2张图片
异常文件:
在这里插入图片描述打开刚才安装的windbg preview,设置一下符号缓存文件路径,以及你自己程序的pdb文件路径,友情提示,Qt在release模式下生成pdb文件需要在pro文件增加如下配置:

QMAKE_CXXFLAGS_RELEASE += $$QMAKE_CFLAGS_RELEASE_WITH_DEBUGINFO
QMAKE_LFLAGS_RELEASE += $$QMAKE_LFLAGS_RELEASE_WITH_DEBUGINFO

好了,继续我们的调试,配置如下
Qt生成dump文件及windbg调试(进阶版)_第3张图片
配置完成之后,将刚才生成的pdb文件拖入command窗口,然后点击自动分析:
Qt生成dump文件及windbg调试(进阶版)_第4张图片
此时会处于BUSY状态,从微软服务器下载各种符号文件,等他完成。

Qt生成dump文件及windbg调试(进阶版)_第5张图片之后,可以看到调用堆栈信息,以及错误代码。094(除0错误),因为之前赋值为0了,==改成=了。

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

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

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


总结

提示:这里对文章进行总结:
例如:以上就是今天要讲的内容,本文仅仅简单介绍了windbg preview的使用以及异常捕获dump文件的调试。博主也是在成长中的菜鸟,文字如有错误,欢迎指正,大家共同探讨。

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