Windows程序崩溃时自动写入MiniDump需调用SetUnhandledExceptionFilter注册顶层异常回调函数,在回调中调用MiniDumpWriteDump生成dump文件;该机制仅捕获未处理SEH异常,不捕获C++异常或abort(),且须在main开头调用,多线程需为各线程单独设置或改用AddVectoredExceptionHandler。

崩溃时自动写入MiniDump需要注册异常处理函数
Windows下程序崩溃(如访问空指针、栈溢出)默认不会生成dump,必须主动注册结构化异常处理(SEH)或向系统注册顶层异常回调。关键函数是 SetUnhandledExceptionFilter,它只对当前线程生效,主线程调用后可捕获未处理的 SEH 异常(EXCEPTION_ACCESS_VIOLATION 等),但捕获不到 C++ 异常(throw)或终止信号(如 abort())。
- 必须在
main()开头或WinMain()一开始就调用,晚了可能错过早期崩溃 - 若程序多线程,且希望捕获其他线程的崩溃,需为每个线程单独设置,或改用更底层的
AddVectoredExceptionHandler(TRUE, ...) - 注册后,回调函数中不能再调用大多数 CRT 函数(如
malloc、printf),避免二次崩溃
MiniDumpWriteDump 的参数选择直接影响调试信息完整性
在异常回调里调用 MiniDumpWriteDump 是写入 dump 的核心步骤。第三个参数 dumpType 决定内容多少,常见组合有:
-
MiniDumpWithFullMemory:包含全部进程内存,dump 文件极大(几百 MB~几 GB),但能还原任意变量值和堆状态 —— 适合本地复现后深度分析 -
MiniDumpWithIndirectlyReferencedMemory+MiniDumpWithThreadInfo:折中方案,保留栈、寄存器、线程上下文、以及栈/寄存器直接引用的内存页,体积通常几 MB~几十 MB,日常崩溃定位足够用 - 漏掉
MiniDumpWithHandleData就看不到句柄表,排查 GDI 泄漏或文件句柄卡死会困难
注意:传入的 hProcess 和 hThread 必须来自 GetThreadContext 或 GetCurrentThread(),不能直接用 GetCurrentProcess() 配任意线程句柄 —— 否则写入失败且返回 FALSE。
写入路径权限不足或目录不存在会导致 dump 静默失败
MiniDumpWriteDump 成功返回 TRUE 仅表示 API 调用成功,不保证文件真正落盘。常见静默失败原因:
立即学习“C++免费学习笔记(深入)”;
- 指定路径所在目录不存在(比如写到
"C:\crashdumps\app.dmp",但crashdumps文件夹没提前创建) - 程序以低完整性级别运行(如 IE Protected Mode、UAC 提权后降权),无法写入
C:\或Program Files下的路径 - 杀毒软件拦截写入行为(尤其对 .dmp 扩展名敏感),此时
GetLastError()可能返回ERROR_ACCESS_DENIED
建议 fallback 到用户临时目录:GetTempPath() + 自定义子目录,并用 CreateDirectory() 确保路径存在。文件名建议含时间戳和 PID,避免多崩溃覆盖:app_20240520_12345.dmp。
Release 版本无符号信息,dump 几乎无法调试
即使 dump 写入成功,若编译时没生成 PDB(如 Release 配置关闭了 /Zi 或未设置 /DEBUG),Windbg 或 VS 打开后只能看到模块名和偏移,看不到函数名、行号、局部变量 —— 相当于只有“骨架”没有“血肉”。
- MSVC 中确保 Release 配置启用:
Configuration Properties → C/C++ → General → Debug Information Format = Program Database (/Zi) - 链接器必须开启:
Configuration Properties → Linker → Debugging → Generate Debug Info = Yes (/DEBUG) - PDB 文件无需随程序分发,但必须与 dump 文件“版本严格对应”:同一份源码、同一套编译参数、同一构建机器生成
一个容易被忽略的点:如果用了增量链接(/INCREMENTAL),PDB 会包含不稳定信息,导致 dump 符号解析错乱 —— 生产环境生成 dump 的构建务必关闭增量链接。


















