最可靠方法是用MiniDumpWriteDump配合SetUnhandledExceptionFilter捕获异常,推荐dump类型为MiniDumpWithFullMemory或MiniDumpWithIndirectlyReferencedMemory,注意权限、磁盘空间及返回值检查;分析首选WinDbg Preview,关键在符号文件(.pdb)与二进制严格匹配。

Windows 下用 MiniDumpWriteDump 生成 dmp 文件
程序崩溃时没自动留 dump,就得自己在关键位置埋点捕获。最可靠的是用 Windows SDK 提供的 MiniDumpWriteDump,它不依赖调试器,进程内就能写。注意不是所有崩溃都能 catch 住——比如栈溢出、非法指令、访问已被释放的内存页,可能根本进不了异常处理函数。
实操建议:
- 用
SetUnhandledExceptionFilter注册顶层异常处理器,在里面调用MiniDumpWriteDump - dump 类型推荐用
MiniDumpWithFullMemory(大但完整)或MiniDumpWithIndirectlyReferencedMemory(折中,能抓到大部分堆对象) - 确保目标路径有写权限,且磁盘空间足够;
MiniDumpWriteDump失败时不抛异常,只返回 FALSE,务必检查返回值 - 别在异常处理里做复杂操作(如 new 内存、加载 DLL),容易二次崩溃
用 WinDbg Preview 分析 .dmp 文件
VS 自带的调试器对 dump 支持弱,尤其多线程、符号路径混乱时经常卡住或显示“no symbols”。WinDbg Preview(Microsoft Store 免费下载)是目前最稳的选择,自带符号服务器自动匹配,还能反汇编、查堆、看线程栈。
常见错误现象:
立即学习“C++免费学习笔记(深入)”;
- 加载 dump 后显示
*** ERROR: Module load failed: 0x80070002→ 符号路径没设对,用.sympath+ srv*https://msdl.microsoft.com/download/symbols补上微软公符 -
!analyze -v报Unable to load image xxx.dll→ 本地缺对应版本的模块文件,把崩溃时的xxx.dll和xxx.pdb放同目录,再用.reload /f xxx.dll - 主线程栈显示
ntdll!NtWaitForMultipleObjects就停住 → 很可能死锁,用~*k看所有线程栈,找谁在等谁
符号文件(.pdb)必须和二进制完全匹配
这是分析失败最常被忽略的一环。dump 里只存地址,没有源码行号或变量名,全靠 .pdb 文件映射。哪怕只是改了个注释重新编译,生成的 .pdb 和旧 .exe 就不再兼容。
使用场景和参数差异:
- 发布 build 时一定要保留
.pdb,并记录其GUID(用dumpbin /headers xxx.exe | findstr "format"查) - 用
symchk /v xxx.exe /s .验证当前目录下.pdb是否匹配 - 如果用 CMake + MSVC,加
set(CMAKE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/pdb")避免 pdb 被覆盖 - 远程机器生成的 dump,必须把对应机器上的
.exe、.dll、.pdb全部拷过来,缺一个就可能看不到局部变量
Linux/macOS 没有 .dmp,但可以用 core dump + GDB
别被后缀误导:Windows 的 .dmp 和 Linux 的 core 是同类东西,只是格式不同。Linux 默认关 core dump,得手动开;macOS 更严格,默认禁用,还得关 SIP 才能生成完整 core。
实操要点:
- Linux:运行前执行
ulimit -c unlimited,确认/proc/sys/kernel/core_pattern指向可写路径 - macOS:先关 SIP(重启进恢复模式 → 终端运行
csrutil disable),再用sudo sysctl -w kern.corefile=/tmp/core.%P - GDB 加载 core:
gdb ./myapp core.1234,然后bt full看完整栈和寄存器值 - 注意:GDB 不会自动读符号,如果可执行文件 strip 过,
bt只能看到地址,必须保留未 strip 的myapp.debug并用file myapp.debug命令加载
真正麻烦的不是生成或打开 dump,而是符号链路断掉一环——编译环境、部署包、调试机三者之间 .pdb 或 .debug 对不上,就只能靠汇编猜逻辑。留档比写代码还重要。

















