windows下使用dbghelp解决未知崩溃问题

文章提供了一种方法,通过Windows下的dbghelp库捕获和分析QT程序在不同环境下导致的未知崩溃问题。代码示例展示了如何生成dmp文件,并使用windbg进行调试,以定位和解决问题。代码已经处理了多字节字符集和Unicode字符集的兼容性,以及32和64位系统的适应性。

前言

编写QT程序后在自己电脑测试无问题,但是换一个电脑就会出现未知的崩溃问题,这种问题分析起来可不是紧靠加日志就可以解决的,所以需要借助windows下dbghelp来捕获崩溃时堆栈,生成dmp文件
在使用windbg进行分析

代码

以下代码已对多字节字符集和 Unicode 字符集进行了兼容,并且支持32和64位,可以直接将文件放入自己项目中,也可编译成动态库,但是需要注意动态库字符集及位数和工程使用的字符集和位数要一致。记得在链接器加入shlwapi.lib

// windump.h
#ifndef __WIN_DUMP_H__
#define __WIN_DUMP_H__

#include <string>
#include <atomic>

#if defined(_UNICODE) || defined(UNICODE)
using String = std::wstring;
#else
using String = std::string;
#endif //  defined(_UNICODE) || defined(UNICODE)

class WinDump
{
   
   
public:
	WinDump() {
   
   }
	~WinDump() {
   
   }

	static void CatchUnhandledException(const String &dmpFilePath);
};

#endif // __WIN_DUMP_H__

// windump.cpp
#pragma warning(disable: 4996)
#include "windump.h"
#include <mutex>
#include <time.h>
#include <Windows.h>
#include <DbgHelp.h>
#include <TlHelp32.h>
#include <Shlwapi.h>

//#if defined(_UNICODE) || defined(UNICODE)
//#error "not support UNICODE"
//#endif //  defined(_UNICODE) || defined(UNICODE)

#if defined(_UNICODE) || defined(UNICODE)
#define SPRINTF wsprintf
#define PRINTF  wprintf
#define _STR	"%ws"
#else</
#define _NO_CRT_STDIO_INLINE #define _IMAGEHLP_SOURCE_ #define _IMAGEHLP64 #include <DbgHelp.h> #pragma comment(lib, "Dbghelp.lib") #include <imagehlp.h> #pragma comment(lib, "imagehlp.lib") // 生成 DMP 文件的函数 void GenerateCrashDump(PEXCEPTION_POINTERS pExceptionInfo) { // 获取桌面路径作为保存位置 wchar_t desktopPath[MAX_PATH]; SHGetFolderPathW(NULL, CSIDL_DESKTOP, NULL, 0, desktopPath); // 构造文件名 (带时间戳) wchar_t dumpPath[MAX_PATH]; SYSTEMTIME st; GetLocalTime(&st); swprintf_s(dumpPath, L"%s\\Crash_%04d%02d%02d_%02d%02d%02d.dmp", desktopPath, st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond); // 创建文件 HANDLE hFile = CreateFileW( dumpPath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile != INVALID_HANDLE_VALUE) { MINIDUMP_EXCEPTION_INFORMATION dumpInfo; dumpInfo.ThreadId = GetCurrentThreadId(); dumpInfo.ExceptionPointers = pExceptionInfo; dumpInfo.ClientPointers = TRUE; // 写入 DMP 文件 (包含模块和线程信息) MiniDumpWriteDump( GetCurrentProcess(), GetCurrentProcessId(), hFile, static_cast<MINIDUMP_TYPE>( MiniDumpWithDataSegs | MiniDumpWithHandleData | MiniDumpWithUnloadedModules), &dumpInfo, NULL, NULL); CloseHandle(hFile); } } // 顶级异常处理器 LONG WINAPI TopLevelExceptionHandler(PEXCEPTION_POINTERS pExceptionInfo) { GenerateCrashDump(pExceptionInfo); return EXCEPTION_EXECUTE_HANDLER; // 结束程序 } // 初始化崩溃处理器 void InitCrashReporting() { SetUnhandledExceptionFilter(TopLevelExceptionHandler); } 生成开始于 16:59... 1>------ 已启动生成: 项目: pdf2word, 配置: Debug Win32 ------ 1>C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\V140\Microsoft.CppBuild.targets(392,5): warning MSB8028: The intermediate directory (C:\Users\admin\Desktop\wzl\project\FyPDFConverter\Temp\Debug\) contains files shared from another project (base.vcxproj, DuiLib.vcxproj, FFileTool.vcxproj). This can lead to incorrect clean and rebuild behavior. 1>stdafx.cpp 1>c:\program files (x86)\microsoft sdks\windows\v7.1a\include\dbghelp.h(1540): warning C4091: “typedef ”: 没有声明变量时忽略“”的左侧 1>c:\program files (x86)\microsoft sdks\windows\v7.1a\include\dbghelp.h(3056): warning C4091: “typedef ”: 没有声明变量时忽略“”的左侧 1>c:\users\admin\desktop\wzl\project\fypdfconverter\pdf2word\format.h(45): warning C4018: “>=”: 有符号/无符号不匹配 1>c:\users\admin\desktop\wzl\project\fypdfconverter\pdf2word\format.h(66): warning C4018: “>=”: 有符号/无符号不匹配 1>c:\program files (x86)\microsoft sdks\windows\v7.1a\include\shlobj.h(1151): warning C4091: “typedef ”: 没有声明变量时忽略“tagGPFIDL_FLAGS”的左侧 1>c:\program files (x86)\microsoft sdks\windows\v7.1a\include\imagehlp.h(136): error C2011: “_LOADED_IMAGE”:“struct”类型重定义 1>c:\program files (x86)\microsoft sdks\windows\v7.1a\include\dbghelp.h(133): note: 参见“_LOADED_IMAGE”的声明 1>c:\program files (x86)\microsoft sdks\windows\v7.1a\include\imagehlp.h(705): error C2011: “_IMAGE_DEBUG_INFORMATION”:“struct”类型重定义 1>c:\program files (x86)\microsoft sdks\windows\v7.1a\include\dbghelp.h(376): note: 参见“_IMAGE_DEBUG_INFORMATION”的声明 1>c:\program files (x86)\microsoft sdks\windows\v7.1a\include\imagehlp.h(877): error C2011: “_MODLOAD_DATA”:“struct”类型重定义 1>c:\program files (x86)\microsoft sdks\windows\v7.1a\include\dbghelp.h(548): note: 参见“_MODLOAD_DATA”的声明 1>c:\program files (x86)\microsoft sdks\windows\v7.1a\include\imagehlp.h(885): error C2011: “_MODLOAD_CVMISC”:“struct”类型重定义 1>c:\program files (x86)\microsoft sdks\windows\v7.1a\include\dbghelp.h(556): note: 参见“_MODLOAD_CVMISC”的声明 1>c:\program files (x86)\microsoft sdks\windows\v7.1a\include\imagehlp.h(894): error C2011: “_MODLOAD_PDBGUID_PDBAGE”:“struct”类型重定义 1>c:\program files (x86)\microsoft sdks\windows\v7.1a\include\dbghelp.h(565): note: 参见“_MODLOAD_PDBGUID_PDBAGE”的声明 1>c:\program files (x86)\microsoft sdks\windows\v7.1a\include\imagehlp.h(904): error C2365: “AddrMode1616”: 重定义;以前的定义是“枚举数” 1>c:\program files (x86)\microsoft sdks\windows\v7.1a\include\dbghelp.h(575): note: 参见“AddrMode1616”的声明 1>c:\program files (x86)\microsoft sdks\windows\v7.1a\include\imagehlp.h(905): error C2365: “AddrMode1632”: 重定义;以前的定义是“枚举数” 1>c:\program files (x86)\microsoft sdks\windows\v7.1a\include\dbghelp.h(576): note: 参见“AddrMode1632”的声明 1>c:\program files (x86)\microsoft sdks\windows\v7.1a\include\imagehlp.h(906): error C2365: “AddrModeReal”: 重定义;以前的定义是“枚举数” 1>c:\program files (x86)\microsoft sdks\windows\v7.1a\include\dbghelp.h(577): note: 参见“AddrModeReal”的声明 1>c:\program files (x86)\microsoft sdks\windows\v7.1a\include\imagehlp.h(908): error C2365: “AddrModeFlat”: 重定义;以前的定义是“枚举数” 1>c:\program files (x86)\microsoft sdks\windows\v7.1a\include\dbghelp.h(579): note: 参见“AddrModeFlat”的声明 1>c:\program files (x86)\microsoft sdks\windows\v7.1a\include\imagehlp.h(908): error C2371: “ADDRESS_MODE”: 重定义;不同的基类型 1>c:\program files (x86)\microsoft sdks\windows\v7.1a\include\dbghelp.h(579): note: 参见“ADDRESS_MODE”的声明 1>c:\program files (x86)\microsoft sdks\windows\v7.1a\include\imagehlp.h(910): error C2011: “_tagADDRESS64”:“struct”类型重定义 1>c:\program files (x86)\microsoft sdks\windows\v7.1a\include\dbghelp.h(581): note: 参见“_tagADDRESS64”的声明 1>c:\program files (x86)\microsoft sdks\windows\v7.1a\include\imagehlp.h(920): error C2011: “_tagADDRESS”:“struct”类型重定义 1>c:\program files (x86)\microsoft sdks\windows\v7.1a\include\dbghelp.h(591): note: 参见“_tagADDRESS”的声明 1>c:\program files (x86)\microsoft sdks\windows\v7.1a\include\imagehlp.h(932): error C2084: 函数“void Address32To64(LPADDRESS,LPADDRESS64)”已有主体 1>c:\program files (x86)\microsoft sdks\windows\v7.1a\include\dbghelp.h(599): note: 参见“Address32To64”的前一个定义 1>c:\program files (x86)\microsoft sdks\windows\v7.1a\include\imagehlp.h(933): error C2027: 使用了未定义类型“_tagADDRESS64” 1>c:\program files (x86)\microsoft sdks\windows\v7.1a\include\dbghelp.h(581): note: 参见“_tagADDRESS64”的声明 1>c:\program files (x86)\microsoft sdks\windows\v7.1a\include\imagehlp.h(933): error C2227: “->Offset”的左边必须指向类/结构/联合/泛型类型 ..... 1>c:\program files (x86)\microsoft sdks\windows\v7.1a\include\dbghelp.h(1405): note: 参见“_IMAGEHLP_CBA_READ_MEMORY”的声明 1>c:\program files (x86)\microsoft sdks\windows\v7.1a\include\imagehlp.h(1742): error C2365: “sevInfo”: 重定义;以前的定义是“枚举数” 1>c:\program files (x86)\microsoft sdks\windows\v7.1a\include\dbghelp.h(1413): note: 参见“sevInfo”的声明 1>c:\program files (x86)\microsoft sdks\windows\v7.1a\include\imagehlp.h(1743): error C2365: “sevProblem”: 重定义;以前的定义是“枚举数” 1>c:\program files (x86)\microsoft sdks\windows\v7.1a\include\dbghelp.h(1414): note: 参见“sevProblem”的声明 1>c:\program files (x86)\microsoft sdks\windows\v7.1a\include\imagehlp.h(1744): error C2365: “sevAttn”: 重定义;以前的定义是“枚举数” 1>c:\program files (x86)\microsoft sdks\windows\v7.1a\include\dbghelp.h(1415): note: 参见“sevAttn”的声明 1>c:\program files (x86)\microsoft sdks\windows\v7.1a\include\imagehlp.h(1744): fatal error C1003: 错误计数超过 100;正在停止编译 1>已完成生成项目“pdf2word.vcxproj”的操作 - 失败。 ========== 生成: 0 成功,1 失败,0 最新,0 已跳过 ========== ========== 生成 于 16:59 完成,耗时 02.337 秒 ==========
06-13
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值