SetUnhandledExceptionFilter比try/catch更可靠,因其能捕获访问违规、栈溢出等结构化异常,且在进程终止前调用,确保堆栈与内存上下文完整;需尽早注册、避免回调中调用不安全API,并正确选用MINIDUMP_TYPE参数组合。

Windows下C++程序崩溃时能自动生成Dump文件,关键不是靠异常捕获逻辑,而是接管未处理异常和系统级崩溃信号——SetUnhandledExceptionFilter 是最直接有效的入口点。
为什么SetUnhandledExceptionFilter比try/catch更可靠
普通try/catch捕获不到访问违规(ACCESS_VIOLATION)、栈溢出、向量寄存器非法使用等结构化异常(SEH),这些才是导致进程突然退出的主因。而SetUnhandledExceptionFilter注册的回调函数会在系统准备终止进程前被调用,此时堆栈、内存、线程上下文都还完整,适合写入Dump。
- 必须在
main()开头或DLL入口(DllMain)中尽早注册,晚于线程创建可能漏掉子线程崩溃 - 仅对当前进程有效,多进程场景需每个进程单独设置
- 与CRT的
_set_invalid_parameter_handler、signal(SIGSEGV)不冲突,但后者覆盖范围小得多
MiniDumpWriteDump调用时的关键参数选择
生成可用Dump的核心是传对MINIDUMP_TYPE标志位。只传MiniDumpNormal几乎没调试价值;但全开(如加MiniDumpWithFullMemory)会导致Dump文件过大(几百MB+),且部分内存页可能已被释放或受保护而写入失败。
- 推荐组合:
MiniDumpWithDataSegs | MiniDumpWithUnloadedModules | MiniDumpWithIndirectlyReferencedMemory | MiniDumpWithThreadInfo - 务必传入崩溃时的
EXCEPTION_POINTERS*(来自过滤器回调),而非NULL——否则无法还原异常现场 - 目标文件路径需确保目录存在且进程有写权限(常见坑:写到
C:\Program Files\下因UAC失败)
如何避免Dump写入失败的典型场景
即使注册了过滤器、参数也正确,仍常遇到Dump为空、大小为0、或写入一半就中断。根本原因往往是回调函数内执行了不安全操作。
Windows 命令行编码与兼容规范。涵盖 GBK/UTF-8 编码、PowerShell/pwsh 互操作、Python/Node.js、Git 配置及代码生成规则。适用于 Windows 10/11 + MSYS2/Git Bash 环境下的所有命令行操作。
立即学习“C++免费学习笔记(深入)”;
- 禁止在过滤器回调里调用
malloc、new、printf、std::string构造等依赖堆或CRT锁的操作——崩溃后堆可能已损坏或被锁定 - 避免跨DLL调用(尤其非静态链接的CRT),应静态链接或只调用kernel32.dll中的API(如
CreateFileW、WriteFile、CloseHandle) - 文件名建议用绝对路径+时间戳(如
crash_20241105_142318.dmp),避免相对路径解析失败或重名覆盖
附加:64位程序要注意MiniDumpWriteDump的句柄兼容性
32位程序调用MiniDumpWriteDump写64位进程Dump会失败(错误码ERROR_PARTIAL_COPY),反之亦然。但你的程序自身是32/64位,不影响它为自己写Dump——只要确保链接的dbghelp.lib版本匹配(VS安装目录下的bin/Hostx64/或Hostx86/对应版本)。
- 检查链接库路径是否含
x64字样(64位构建)或x86(32位构建) - 运行时可调用
IsWow64Process辅助判断,但写自身Dump时无需此步 - 若用
LoadLibrary动态加载dbghelp.dll,必须从System32(64位)或SysWOW64(32位)加载对应版本,不能硬编码路径
真正难的不是调用MiniDumpWriteDump,而是在崩溃发生的那一瞬间,克制住所有“想做点别的”冲动——不分配内存、不格式化字符串、不查表、不调用第三方SDK。越简单,越可能成功写出一份能定位问题的Dump。

















