Qt环境生成dump解决异常崩溃

当Qt程序在客户环境中异常崩溃难以定位时,可以通过生成dump文件并使用winDbg进行分析。在Qt项目中添加特定配置以生成调试信息和pdb文件,然后设置异常处理函数来捕获崩溃信息。使用winDbg加载dump文件,通过自动分析找到出错的源代码行,辅助解决疑难bug。确保exe、pdb和源代码版本一致,以获得准确的调试结果。
摘要由CSDN通过智能技术生成

背景

对于经常使用C/C++的伙伴来说,程序有问题动不动就罢工崩溃的问题简直不能太熟悉了。比如本地测试通过打包发布的release版本Qt程序,在客户环境下仍可能出现异常崩溃的问题。一般通过客户反馈以及分析系统运行日志,问题基本都能够得到快速解决。但总会有些bug很难定位,这种情况下通过生成dump文件,结合winDbg程序定位问题将是一个很好的解决方式。

内容新增

-------------------------------------------------------------------分割线----------------------------------------------------------
VS作为宇宙第一IDE,名声在外自然要利用起来。对于编写Qt程序,QtCreator还是最香的。但VS的强大的调试能力还是无出其右。对于疑难问题,将QT程序移植到VS环境运行调试,是可以直接跳转到问题代码行的,这也是不错的可行方法。
-------------------------------------------------------------------分割线----------------------------------------------------------

具体操作

一、生成dump文件

在QtCreator中默认不支持生成dump文件,且发行版release模式不含调试信息,因此这里需要进行以下两步设置。

1.在.pro文件中添加如下语句,来产生调试信息以及pdb文件

QMAKE_CXXFLAGS_RELEASE = $$QMAKE_CFLAGS_RELEASE_WITH_DEBUGINFO
QMAKE_LFLAGS_RELEASE = $$QMAKE_LFLAGS_RELEASE_WITH_DEBUGINFO
LIBS += -lDbgHelp

2.程序文件中添加可以产生dump文件的代码。代码直接复制可用,不再讲解含义

LONG crashHandler(EXCEPTION_POINTERS *pException)
{
    QString curDataTime = QDateTime::currentDateTime().toString("yyyyMMddhhmmss");
    QString dumpName = curDataTime + ".dmp";

    HANDLE dumpFile = CreateFile((LPCWSTR)QString("./" + dumpName).utf16(),GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
    if(dumpFile != INVALID_HANDLE_VALUE)
    {
        MINIDUMP_EXCEPTION_INFORMATION dumpInfo;
        dumpInfo.ExceptionPointers = pException;
        dumpInfo.ThreadId = GetCurrentThreadId();
        dumpInfo.ClientPointers = TRUE;

        MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(),dumpFile, MiniDumpNormal, &dumpInfo, NULL, NULL);
        CloseHandle(dumpFile);
    }
    else
    {
        qDebug() << "dumpFile not vaild";
    }
    
    return EXCEPTION_EXECUTE_HANDLER;
}

//防止CRT(C runtime)函数报错可能捕捉不到
void DisableSetUnhandledExceptionFilter()
{
    void* addr = (void*)GetProcAddress(LoadLibrary(L"kernel32.dll"), "SetUnhandledExceptionFilter");
    if(addr)
    {
        unsigned char code[16];
        int size = 0;

        code[size++] = 0x33;
        code[size++] = 0xC0;
        code[size++] = 0xC2;
        code[size++] = 0x04;
        code[size++] = 0x00;

        DWORD dwOldFlag, dwTempFlag;
        VirtualProtect(addr, size, PAGE_READWRITE, &dwOldFlag);
        WriteProcessMemory(GetCurrentProcess(), addr, code, size, NULL);
        VirtualProtect(addr, size, dwOldFlag, &dwTempFlag);
    }
}

int main(int argc, char *argv[])
{
    //注冊异常捕获函数
    SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER)crashHandler);
    DisableSetUnhandledExceptionFilter();

    QApplication a(argc, argv);
    Widget w;
    w.show();

    return a.exec();
}

3.清除并重新qmake运行,产生pdb文件以及运行程序。此种情况下应用程序崩溃将会预定位置产生dump文件。

二、使用dump文件

1.假设此时程序崩溃得到dump文件,打开winDbg软件(需要自行下载,安装很简单),分别设置源代码路径、pdb文件路径、dump路径,确定后软件跳转至分析界面。
路径设置
2.点击自动分析(!anasyle -v),产生堆栈信息,之后可以查看到出错的源代码行数
数据分析

注意事项

以上提供了一个解决异常崩溃的思路,不是终极解决方案,虽然无法保证100%解决问题,但是可能会有奇效,个人建议还是逻辑分析为主,问题基本都能解决,还能锻炼分析能力,避免再写类似bug。

注意点如下:
1.应保证打包的exe,pdb,源代码版本一致,否则调试可能有偏差。
2.dump文件不保证一定产生,可能有些错误捕捉不到。
3.!anasyle -v自动分析后,大部分时候可以直接定位到出错行数,很直观。但也存在找不到行数的情况,但是有清晰的堆栈信息可以帮助分析问题。

Qt开发过程中,如果程序发生崩溃并且没有生成dump文件,我们可以尝试以下解决办法。 首先,我们需要确保程序运行在“Release”模式下,因为在“Debug”模式下,Qt会自动生成dump文件。所以,我们可以尝试将程序重新编译并运行在“Release”模式下,这样可能会生成dump文件。 如果重新编译运行仍然没有生成dump文件,我们可以通过设置特定的环境变量来启用dump文件生成。在Windows系统中,我们可以设置环境变量"_NT_SYMBOL_PATH",指定符号文件的路径。符号文件是用于分析dump文件的关键文件。我们可以将Qt的符号文件路径添加到这个环境变量中,然后再次运行程序,希望能生成dump文件。 另外,我们可以使用第三方工具来生成dump文件。有一些工具可以监视程序的崩溃,并自动生成dump文件。比如,我们可以使用Microsoft的工具ProcDump来监视Qt程序,一旦程序崩溃,它将自动生成dump文件。我们只需简单设置一些参数,并运行这个工具,即可获得所需的dump文件。 需要指出的是,生成dump文件只是为了帮助我们分析程序崩溃的原因。当我们获取到dump文件后,仍然需要使用相应的分析工具来分析它,以确定程序崩溃的根本原因。对于Qt而言,我们可以使用GDB、Windbg等工具进行分析。 总结起来,如果Qt程序奔溃没有生成dump文件,我们可以尝试重新编译并运行在“Release”模式下,设置环境变量来启用dump文件生成,或者使用第三方工具来监视程序崩溃生成dump文件。然后,使用相应的分析工具来分析dump文件,帮助我们找到程序崩溃的原因。
评论 17
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

你是周小哥啊

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值