当前位置: 代码网 > it编程>编程语言>C/C++ > Windows下Qt使用dump定位崩溃位置(1)

Windows下Qt使用dump定位崩溃位置(1)

2024年05月31日 C/C++ 我要评论
软件调试 Windows下Qt使用dump定位崩溃位置(1) 目录软件调试Windows下Qt使用dump定位崩溃位置(1)1、Qt崩溃定位方法2、 什么是dump文件3、使用vs调试dmp4、下载Windows符号表5、下载Qt符号表6、主要代码7、源代码 更多精彩内容 个人内容分类汇总 ...

软件调试

windows下qt使用dump定位崩溃位置(1)

更多精彩内容
👉个人内容分类汇总 👈
👉c++软件调试、异常定位 👈

本文说的方法只适合windows下msvc编译器(不支持mingw),如果需要跨平台可以👉看这一篇

1、qt崩溃定位方法

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

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

2、 什么是dump文件

  • dump文件通常是指程序或系统崩溃时,将内存中的数据转储并保存到磁盘文件中的一种文件格式。dump文件包含了程序崩溃时的内存状态、寄存器状态、线程状态等信息,可以帮助开发人员诊断和解决故障。
  • dump文件一般是以二进制格式保存在磁盘上,其内容包含了程序或系统崩溃时内存中的所有数据,包括代码、数据、栈、堆等。dump文件的大小通常很大,可能达到几百mb或几gb,因此在进行分析和调试时需要使用专门的工具和技术。
  • 在windows系统中,dump文件一般使用windows的调试工具windbg来分析。windbg可以读取dump文件,并提供调试命令和分析工具,帮助开发人员进行故障诊断和调试。除了windbg,还有其他的调试工具和分析工具可以读取和分析dump文件,例如visual studio的调试器、qtcreator和第三方工具如ida pro等。

3、使用vs调试dmp

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

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

    img

  3. 点击1️⃣【设置符号路径】,进行如下设置;

    1. 如果是第一次调试需要勾选microsoft符号服务器2️⃣:会从网络下载调试使用的符号文件,然后将符号文件下载到5️⃣位置,以后就不需要勾选符号服务器了;
    2. 点击“+”号3️⃣添加【testcrashhandler.pdb】6️⃣文件所在路径4️⃣

    img

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

    img

  5. 成功定位到崩溃位置

    img

4、下载windows符号表

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

img

5、下载qt符号表

这种方法可以选择下载部分调试符号表,体积比较小。

  1. 选择系统环境https://download.qt.io/online/qtsdkrepository/

    img

  2. 选择desktop

    img

  3. 选择安装的qt版本,我的时5.14.2

    img

  4. 选择调试编译器版本,我的是msvc2017-64

    img

  5. 下载需要调试的模块的符号表

    img

6、主要代码

  • 默认情况下只有debug可用生成可用的dmp文件,release对程序的编译进行了优化,并且不生成pdb符号文件,所以无法进行调试,如果想要release可用调试,需要在pro文件进行下列设置

    # 在release生成用于调试dump的信息,包括【禁用release编译优化】、【生成pdb符号表】,但是这些设置会降低程序性能,和debug差不多
    config(release, debug|release) {
        qmake_cxxflags_release -= -o2
        qmake_cxxflags_release += -o0
        qmake_cxxflags_release += /zi
        qmake_lflags_release += /debug /opt:ref /opt:icf                # 生成 pdb符号文件,功能和下一行一样,但是最好用这一行,显示指定编译选项
    #    qmake_lflags_release += $$qmake_lflags_release_with_debuginfo
    
        # 打印变量参数值
        message(qmake_cxxflags_release变量值:$$qmake_cxxflags_release)
        message(qmake_lflags_release变量值:$$qmake_lflags_release)
    }
    
  • main.cpp

    #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
    }
    
    

7、源代码

gitee
github

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2026  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com