当前位置: 首页 > news >正文

Qt下生成pdb文件,并在exe崩溃时生成dmp文件,且由dmp查询崩溃原因

一、编译时生成pdb文件

选择profile编译即可,在此模式下,既可享受release的运行速度,又可以享受debug的符号查找。
发布的程序可以正常运行在生产环境,尤其是适合在一些实时性要求高的项目中。
在这里插入图片描述

二、在exe崩溃时生成dmp文件

参考:
https://blog.csdn.net/a844651990/article/details/85225273

声明函数

DumpHelper.h

#ifndef DUMPHELPER_H
#define DUMPHELPER_H

#include <QSystemSemaphore>
#include <QDir>
#include <QDateTime>
#include <QDebug>

#include <tchar.h>
#include <Windows.h>
#include <DbgHelp.h>

#pragma comment(lib, "user32.lib")
#pragma comment(lib, "DbgHelp.Lib")

int GenerateMiniDump(PEXCEPTION_POINTERS pExceptionPointers)
{
    // 定义函数指针
    typedef BOOL(WINAPI * MiniDumpWriteDumpT)(
        HANDLE,
        DWORD,
        HANDLE,
        MINIDUMP_TYPE,
        PMINIDUMP_EXCEPTION_INFORMATION,
        PMINIDUMP_USER_STREAM_INFORMATION,
        PMINIDUMP_CALLBACK_INFORMATION
        );
    // 从 "DbgHelp.dll" 库中获取 "MiniDumpWriteDump" 函数
    MiniDumpWriteDumpT pfnMiniDumpWriteDump = NULL;
    HMODULE hDbgHelp = LoadLibrary(_T("DbgHelp.dll"));
    if (NULL == hDbgHelp)
    {
        return EXCEPTION_CONTINUE_EXECUTION;
    }
    pfnMiniDumpWriteDump = (MiniDumpWriteDumpT)GetProcAddress(hDbgHelp, "MiniDumpWriteDump");

    if (NULL == pfnMiniDumpWriteDump)
    {
        FreeLibrary(hDbgHelp);
        return EXCEPTION_CONTINUE_EXECUTION;
    }
    // 创建 dmp 文件件
    TCHAR szFileName[MAX_PATH] = { 0 };
    TCHAR szVersion[] = L"DumpFile";
    SYSTEMTIME stLocalTime;
    GetLocalTime(&stLocalTime);
    wsprintf(szFileName, L"%s-%04d%02d%02d-%02d%02d%02d.dmp",
        szVersion, stLocalTime.wYear, stLocalTime.wMonth, stLocalTime.wDay,
        stLocalTime.wHour, stLocalTime.wMinute, stLocalTime.wSecond);
    HANDLE hDumpFile = CreateFile(szFileName, GENERIC_READ | GENERIC_WRITE,
        FILE_SHARE_WRITE | FILE_SHARE_READ, 0, CREATE_ALWAYS, 0, 0);
    if (INVALID_HANDLE_VALUE == hDumpFile)
    {
        FreeLibrary(hDbgHelp);
        return EXCEPTION_CONTINUE_EXECUTION;
    }
    // 写入 dmp 文件
    MINIDUMP_EXCEPTION_INFORMATION expParam;
    expParam.ThreadId = GetCurrentThreadId();
    expParam.ExceptionPointers = pExceptionPointers;
    expParam.ClientPointers = FALSE;
    pfnMiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(),
        hDumpFile, MiniDumpWithDataSegs, (pExceptionPointers ? &expParam : NULL), NULL, NULL);
    // 释放文件
    CloseHandle(hDumpFile);
    FreeLibrary(hDbgHelp);
    return EXCEPTION_EXECUTE_HANDLER;
}

LONG WINAPI ExceptionFilter(LPEXCEPTION_POINTERS lpExceptionInfo)
{
    // 这里做一些异常的过滤或提示
    if (IsDebuggerPresent()) {
        return EXCEPTION_CONTINUE_SEARCH;
    }
    return GenerateMiniDump(lpExceptionInfo);
}

long __stdcall errCallback(_EXCEPTION_POINTERS*  pException)
{
 
//     //用于崩溃重启
//    // 信号量的意义,把操作共享内存的代码锁住。因为有可能同时启动, 防止并发
//    QSystemSemaphore sema("DyError", 1, QSystemSemaphore::Open);
//    sema.acquire();


    QDir dir;
    dir.mkdir("./dumps");
    dir.cd("./dumps");

    /*
      ***保存数据代码***
    */

    QString fileName = dir.path() + "/" +
                       QDateTime::currentDateTime().toString("yyyyMMdd_HHmmss.zzz") + ".dmp";

    LPCWSTR pFileName = (LPCWSTR)fileName.unicode();

    //创建 Dump 文件
    HANDLE hDumpFile = CreateFile(pFileName,
                                  GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
    qDebug() << "create dumpFile:" << hDumpFile << INVALID_HANDLE_VALUE;
    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);
    }

//    delete  unimem;

//    qDebug() << "start application:" << QProcess::startDetached(qApp->applicationFilePath(), QStringList());//重启

//    qApp->quit();
    qApp->exit(-1);

    return EXCEPTION_EXECUTE_HANDLER;
}


#endif // DUMPHELPER_H

调用函数

在main函数中注册

main.cpp

#include "mainwindow.h"

#include <QApplication>

#include "DumpHelper.h"

int main(int argc, char *argv[])
{
//    SetUnhandledExceptionFilter(ExceptionFilter); // dmp文件比较大
    SetUnhandledExceptionFilter(errCallback); // dmp文件比较小

    QApplication a(argc, argv);
    MainWindow w;
    w.show();
    return a.exec();
}

三、经由dmp文件查询崩溃原因

在我们写好程序,编译好,且发布了给客户时,一定要注意保存几个东西:此时的源码、此时的exe+pdb文件。
在给到客户的程序发生了崩溃,产生了dmp文件后,我们需要把我们当时发布的exe、pdb、客户发给我们的dmp文件放在一起,然后用vs打开,进行调试操作。

基本前提

能够查询溯源的前提是对软件发布时的东西做好了备份:源码、pdb、exe
下面以实例说明。
目前,有一个 versionTest 项目,经过编译后,发布了v1版本。内容如下:
在这里插入图片描述

并且,在发布时,我也备份了对应的源码、pdb文件
在这里插入图片描述

假设此时,用户发现软件崩溃了,在对应目录生成了dmp文件,他将文件发给了我。

1.将对应的dmp文件、exe文件、pdb文件拷贝你发布的一份程序目录下

在这里插入图片描述

2.用vs打开dmp文件,并执行调试

在这里插入图片描述在这里插入图片描述

此时它可能会定位到你最新的代码那里去的。

3.自己手动定位一下真正源码位置

在这里插入图片描述在这里插入图片描述
选择你之前备份的文件夹
在这里插入图片描述
自然就对上了。

相关文章:

  • 蜂鸣器、风扇、震动马达
  • 【VRP问题】基于帝国企鹅优化算法求解冷链配送物流车辆调度优化研究
  • 3) 时频分析与傅立叶变换
  • stm32f4xx-I2C
  • 有了这个 Python 库,以后再也不用写正则表达式了
  • 学习python很无聊?看看这几个有意思的代码,拿去整蛊一下好朋友~ 适当娱乐哈
  • 【老生谈算法】matlab实现滤波器设计源码——滤波器设计
  • 后端研发工程师面经——手撕设计模式
  • 1679. K 和数对的最大数目-自定义哈希表解决
  • 【Objective-C内存管理之引用计数】
  • 找工作经验总结——嵌入式软件工程师必备的能力(表达篇)
  • 【vue基础篇】极简 ESLint + Prettier 配置教程
  • 线性代数-----矩阵复习2
  • 个人算法重刷记录
  • Charles日常使用
  • [分享]iOS开发 - 实现UITableView Plain SectionView和table不停留一起滑动
  • [数据结构]链表的实现在PHP中
  • Angular Elements 及其运作原理
  • C++类的相互关联
  • Java小白进阶笔记(3)-初级面向对象
  • Java知识点总结(JavaIO-打印流)
  • Linux学习笔记6-使用fdisk进行磁盘管理
  • MYSQL如何对数据进行自动化升级--以如果某数据表存在并且某字段不存在时则执行更新操作为例...
  • nodejs调试方法
  • RxJS: 简单入门
  • SpiderData 2019年2月25日 DApp数据排行榜
  • 安卓应用性能调试和优化经验分享
  • 产品三维模型在线预览
  • 关键词挖掘技术哪家强(一)基于node.js技术开发一个关键字查询工具
  • 诡异!React stopPropagation失灵
  • 解决iview多表头动态更改列元素发生的错误
  • 全栈开发——Linux
  • 算法-插入排序
  • 你学不懂C语言,是因为不懂编写C程序的7个步骤 ...
  • ​渐进式Web应用PWA的未来
  • ​人工智能之父图灵诞辰纪念日,一起来看最受读者欢迎的AI技术好书
  • ​软考-高级-信息系统项目管理师教程 第四版【第23章-组织通用管理-思维导图】​
  • # 深度解析 Socket 与 WebSocket:原理、区别与应用
  • #162 (Div. 2)
  • #QT(串口助手-界面)
  • #基础#使用Jupyter进行Notebook的转换 .ipynb文件导出为.md文件
  • #我与Java虚拟机的故事#连载02:“小蓝”陪伴的日日夜夜
  • (07)Hive——窗口函数详解
  • (DenseNet)Densely Connected Convolutional Networks--Gao Huang
  • (八)Docker网络跨主机通讯vxlan和vlan
  • (三分钟)速览传统边缘检测算子
  • (终章)[图像识别]13.OpenCV案例 自定义训练集分类器物体检测
  • (转)visual stdio 书签功能介绍
  • (转)程序员疫苗:代码注入
  • (轉貼) 2008 Altera 亞洲創新大賽 台灣學生成果傲視全球 [照片花絮] (SOC) (News)
  • . Flume面试题
  • .NET CF命令行调试器MDbg入门(二) 设备模拟器
  • .net core 6 集成 elasticsearch 并 使用分词器
  • .net core 源码_ASP.NET Core之Identity源码学习
  • .Net Core缓存组件(MemoryCache)源码解析