0
点赞
收藏
分享

微信扫一扫

Qt使用dump定位崩溃位置

caoxingyu 2022-04-06 阅读 134

qt崩溃位置定位

文章目录

1、Qt崩溃定位方法

方法1: 通过日志系统保存程序执行日志信息,在程序崩溃后通过日志信息可分析出程序进行了哪些操作;
方法2:

  • 日志信息并不是万能的,有些情况下日志信息不一定能分析出崩溃问题,这时就需要借助dump文件进行分析;
  • 当程序遇到未处理的异常导致程序崩溃,如果在异常发生之前调用了SetUnhandledExceptionFilter() 函数,异常交给函数处理。因而,在程序开始处增加SetUnhandledExceptionFilter()函数,并在函数中利用适当的方法生成Dump文件,保存崩溃位置信息。

2、 什么是dump文件

  • Dump 文件是进程的内存镜像 , 可以把程序的执行状态通过调试器保存到dump文件中 ;
  • Dump 文件是用来给驱动程序编写人员调试驱动程序用的 , 这种文件必须用专用工具软件打开 , 比如使用 WinDbg , VisualStudio 打开 ;
  • 当我们的程序发布出去之后 , 在客户机上是无法跟踪自己代码的 BUG 的 , 所以 Dump 文件对于我们来说特别有用 ; 我们可以通过 .dmp 文件把出现 BUG 的情况再现 , 然后再现客户环境 (包括堆栈调用等情况) , 设置源码调试路径 , 可以找到出现 BUG 的语句 。

3、使用vs调试dmp

  1. 打开vs,选择继续但无需代码

    在这里插入图片描述

  2. 将dmp文件直接拖如vs中

    在这里插入图片描述

  3. 点击设置符号路径,分别设置代码的符号表路径、可执行程序路径和源代码路径(注意这三个要版本一样,如果代码改过了就不行了),确认设置。

    在这里插入图片描述

  4. 点击 使用仅限本机进行调试

    在这里插入图片描述

  5. 成功定位到崩溃位置

    在这里插入图片描述

4、下载Windows符号表

如果勾选了Microsoft符号服务器或者NuGet.org服务器则可将window符号表下载到下列路径中,在离线环境中也可进行调试。

在这里插入图片描述

5、主要代码

#include "crashhandler.h"
#include <QMessageBox>
#include <QDateTime>
#include <qglobal.h>

#ifdef _MSC_VER
#include <Windows.h>          // Windows.h必须放在DbgHelp.h前,否则编译会报错
#include <DbgHelp.h>
#endif

//MSVC编译器
#ifdef _MSC_VER

#if defined(_MSC_VER) && (_MSC_VER >= 1600)
#pragma execution_character_set("utf-8")
#endif
/**
 * @brief              应用程序崩溃处理程序
 * @param pException
 * @return             EXCEPTION_EXECUTE_HANDLER equ 1 表示我已经处理了异常,可以优雅地结束了
 *                     EXCEPTION_CONTINUE_SEARCH equ 0 表示我不处理,其他人来吧,于是windows调用默认的处理程序显示一个错误框,并结束(qt中会导致窗口卡死一段时间)
 *                     EXCEPTION_CONTINUE_EXECUTION equ -1 表示错误已经被修复,请从异常发生处继续执行
 */
LONG ApplicationCrashHandler(EXCEPTION_POINTERS *pException){//程式异常捕获
    //创建 Dump 文件
    QString strPath = QString("%1.dmp").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd HH-mm-ss"));
#ifdef UNICODE
    LPCWSTR filePath = reinterpret_cast<LPCWSTR>(strPath.utf16());
#else
    LPCSTR filePath = reinterpret_cast<LPCSTR>(strPath.toStdString().data());
#endif // !UNICODE
    HANDLE hDumpFile = CreateFile(filePath, 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((quint64)record->ExceptionCode, 16));
    QString errAdr(QString::number((uint)record->ExceptionAddress, 16));
    QMessageBox::critical(nullptr, "程式崩溃","<FONT size=4><div><b>对于发生的错误,表示诚挚的歉意</b><br/></div>"+
                          QString("<div>错误代码:%1</div><div>错误地址:%2</div></FONT>").arg(errCode).arg(errAdr),
                          QMessageBox::Ok);

    return EXCEPTION_EXECUTE_HANDLER;
}
#endif

void CrashHandler::initCrashHandler()
{
#ifdef _MSC_VER
    SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER)ApplicationCrashHandler);   // 使用win API注册异常处理函数
#endif
}

6、源代码

gitee
github

举报

相关推荐

0 条评论