需在main/winmain开头调用setunhandledexceptionfilter注册顶层seh处理器;异常处理函数中校验参数后,用getcurrentprocess()等正确参数调用minidumpwritedump生成带时间戳的dump文件,并以create_always写入%localappdata%安全路径且flushfilebuffers确保落盘。

当 Windows 程序因访问违规、栈溢出或未处理异常意外终止时,需要在进程崩溃瞬间捕获内存现场并生成可被 WinDbg 或 Visual Studio 加载分析的 MiniDump 文件,确保开发人员能还原调用栈、寄存器状态和模块信息。
注册顶层结构化异常处理(SEH)回调
调用 SetUnhandledExceptionFilter 函数注册自定义异常过滤器,该函数必须在主线程初始化早期执行,否则子线程崩溃无法被捕获。
在 main() 或 WinMain() 开头第一行立即调用:SetUnhandledExceptionFilter(TopLevelExceptionHandler);此函数仅对当前进程有效,且不能在 DLL 的 DllMain 中安全调用。
注意:若程序已启用 /SAFESEH 编译选项,必须确保 TopLevelExceptionHandler 函数地址位于加载的 PE 模块内,否则系统将忽略该过滤器。
实现异常过滤器并触发 MiniDumpWriteDump
在 TopLevelExceptionHandler 函数中,首先检查 EXCEPTION_POINTERS 参数是否为空,空值会导致后续写入崩溃。
调用 MiniDumpWriteDump 时,第三个参数 hProcess 必须传 GetCurrentProcess(),传错句柄(如 NULL 或其他进程)会导致函数返回 FALSE 且无 dump 文件生成。
第二个参数 ProcessId 应传 GetCurrentProcessId();第四个参数 ExceptionParam 必须传入传入的 ExceptionInfo 指针,不可为 NULL —— 【NULL 将导致 MiniDumpWriteDump 静默失败】。
第五个参数需传入 MINIDUMP_TYPE 类型组合,推荐使用 MiniDumpWithIndirectlyReferencedMemory | MiniDumpScanMemory | MiniDumpWithUnloadedModules,兼顾堆内存引用链与卸载模块符号定位能力。
生成带时间戳与进程名的 dump 文件路径
第一步:调用 GetModuleFileName(NULL, szPath, MAX_PATH) 获取当前可执行文件全路径。
第二步:用 PathFindFileNameA 提取文件名(不含路径),再用 PathRemoveExtensionA 去掉 .exe 后缀。
第三步:调用 GetLocalTime 获取 SYSTEMTIME 结构,用 sprintf_s 拼接格式为 "%s_%04d%02d%02d_%02d%02d%02d.dmp" 的完整路径字符串。
这一步必须在 MiniDumpWriteDump 调用前完成,因为崩溃后部分 CRT 函数(如 localtime)可能不可靠;路径字符串缓冲区长度至少设为 MAX_PATH * 2,避免截断。
确保 dump 文件写入磁盘且不被杀软拦截
方法一:以 CREATE_ALWAYS 标志调用 CreateFile,并显式设置 FILE_ATTRIBUTE_NORMAL 属性,绕过某些安全软件对临时/隐藏文件的拦截。
方法二:将 dump 写入 %LOCALAPPDATA%\YourApp\CrashDumps 目录,该路径用户有完全控制权限,且不在系统保护目录(如 Program Files)内,避免 UAC 或虚拟化重定向干扰。
方法三:在 MiniDumpWriteDump 返回 TRUE 后,立即调用 FlushFileBuffers(hFile),防止系统缓存未落盘导致 dump 文件内容不完整 —— 【不刷新缓存可能导致生成 0 字节或截断文件】。
关闭文件句柄前,务必检查 FlushFileBuffers 返回值,失败时记录 GetLastError() 到事件日志,便于排查磁盘满或权限问题。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











