一、程序崩溃时如何自动生成 Dump 文件
步骤一:包含必要的头文件
#include <Windows.h>
#include <DbgHelp.h>
pro文件中添加库
LIBS += -lDbghelp
步骤二:创建生成 Dump 的函数
void CreateMiniDump(EXCEPTION_POINTERS* pep)
{
SYSTEMTIME stLocalTime;
GetLocalTime(&stLocalTime);
TCHAR szFileName[MAX_PATH];
swprintf_s(szFileName, MAX_PATH, L"CrashDump_%04d%02d%02d_%02d%02d%02d.dmp",
stLocalTime.wYear, stLocalTime.wMonth, stLocalTime.wDay,
stLocalTime.wHour, stLocalTime.wMinute, stLocalTime.wSecond);
HANDLE hFile = CreateFile(szFileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL, NULL);
if ((hFile != NULL) && (hFile != INVALID_HANDLE_VALUE))
{
MINIDUMP_EXCEPTION_INFORMATION mdei;
mdei.ThreadId = GetCurrentThreadId();
mdei.ExceptionPointers = pep;
mdei.ClientPointers = TRUE;
BOOL success = MiniDumpWriteDump(
GetCurrentProcess(),
GetCurrentProcessId(),
hFile,
MiniDumpWithFullMemory, // 你也可以用 MiniDumpNormal
&mdei,
nullptr,
nullptr);
CloseHandle(hFile);
if (success) {
QString msg = QString("程序崩溃啦!\nDump 文件已保存为:\n%1").arg(QString::fromWCharArray(szFileName));
MessageBoxW(NULL, (LPCWSTR)msg.utf16(), L"崩溃提示", MB_OK | MB_ICONERROR);
} else {
MessageBoxW(NULL, L"程序崩溃啦!但保存 Dump 文件失败。", L"崩溃提示", MB_OK | MB_ICONERROR);
}
}
}
步骤三:设置异常处理函数
LONG WINAPI MyUnhandledExceptionFilter(EXCEPTION_POINTERS* pExceptionInfo) {
CreateMiniDump(pExceptionInfo);
return EXCEPTION_EXECUTE_HANDLER;
}
步骤四:在程序入口设置异常处理
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
SetUnhandledExceptionFilter(MyUnhandledExceptionFilter);
// 故意触发异常(测试用)
int* p = nullptr;
*p = 42;
return a.exec();
}
二、支持多线程中的异常捕获
C++ 中 SetUnhandledExceptionFilter 只能捕获未被 catch 的 SEH 异常。如果你用 Qt 的多线程(如 QThread),线程内部抛出的是 std::exception 或 Qt 异常,是不会自动走到 UnhandledExceptionFilter 的。
方法:在线程函数中加 __try/__except 包裹
unsigned __stdcall ThreadFunc(void* param)
{
__try {
// 正常线程代码
int* p = nullptr;
*p = 100; // 故意异常
}
__except (CreateMiniDump(GetExceptionInformation()), EXCEPTION_EXECUTE_HANDLER) {
// 可选处理
}
return 0;
}
如果使用的是 QThread,可以重写 run() 方法,并包裹异常处理:
void MyThread::run()
{
__try {
// 正常逻辑
}
__except (CreateMiniDump(GetExceptionInformation()), EXCEPTION_EXECUTE_HANDLER) {
// 崩溃时生成 dump
}
}
三、在 DLL 中使用 Dump 捕获
如果写的是一个 DLL 插件,也可以捕获崩溃,在 DllMain 中设置异常处理:
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved)
{
if (fdwReason == DLL_PROCESS_ATTACH) {
SetUnhandledExceptionFilter(MyUnhandledExceptionFilter);
}
return TRUE;
}
四、封装成可复用类
可以把这整个流程封装成一个类,如:
class DumpCatcher
{
public:
static void Init() {
SetUnhandledExceptionFilter(UnhandledFilter);
}
private:
static LONG WINAPI UnhandledFilter(EXCEPTION_POINTERS* pExceptionInfo) {
CreateMiniDump(pExceptionInfo);
return EXCEPTION_EXECUTE_HANDLER;
}
static void CreateMiniDump(EXCEPTION_POINTERS* pep);
};
然后在程序入口调用:
DumpCatcher::Init();
五、MiniDumpWriteDump函数详解
MiniDumpWriteDump 是 Windows 平台下由 DbgHelp 库提供的函数,用于在应用程序崩溃或其他时机生成进程的内存转储(.dmp)文件,便于事后用调试器(如 Visual Studio、WinDbg)分析崩溃原因和程序状态。
函数原型:
BOOL MiniDumpWriteDump(
HANDLE hProcess,
DWORD ProcessId,
HANDLE hFile,
MINIDUMP_TYPE DumpType,
PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,
PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,
PMINIDUMP_CALLBACK_INFORMATION CallbackParam
);
参数说明:
常用 MINIDUMP_TYPE: