跳转到主内容
新派编程网 - 新潮编程理念,全新技术课堂!

C++如何利用SEH捕获Windows程序崩溃 _ 结构化异常处理方案【干货】

__try/__except 能捕获 Windows 结构化异常,如 EXCEPTION_ACCESS_VIOLATION、EXCEPTION_INTEGER_DIVIDE_BY_ZERO、EXCEPTION_STACK_OVERFLOW 和 EXCEPTION_INVALID_HANDLE,但仅限当前线程当前函数栈,不处理 C++ 异常。 C++ 的
try
/
catch
捕不到崩溃,必须用 Windows 原生 SEH(
__try
/
__except
)或
SetUnhandledExceptionFilter
才能真正拦截访问违规、除零、栈溢出等底层异常。 __try/__except 能捕获哪些崩溃? 它专为 Windows 结构化异常设计,可响应硬件级错误,比如:
ACCESS_VIOLATION
(解引用空指针、野指针读写)
INTEGER_DIVIDE_BY_ZERO
(整数除零)
STACK_OVERFLOW
(递归过深或大数组栈分配)
INVALID_HANDLE
(非法句柄操作) 但注意:
__try
/
__except
只对当前函数调用栈生效,不能跨线程捕获;且它不处理 C++ 异常(
throw
抛出的),那是
try
/
catch
的职责。 filter-expression 返回值决定后续行为
__except
后面的表达式不是布尔值,而是三个预定义常量之一: 立即学习 “ C++免费学习笔记(深入) ”;
EXCEPTION_EXECUTE_HANDLER
:执行
__except
块,然后从
__try
块外继续执行(**不推荐用于崩溃场景,栈已损坏,强行恢复极易二次崩溃**)
EXCEPTION_CONTINUE_SEARCH
:忽略本次异常,交由上层 SEH 处理器或系统默认处理(最常用)
EXCEPTION_CONTINUE_EXECUTION
:**极危险**——让 CPU 重新执行触发异常的那条指令(仅适用于可修复的瞬时状态,如页面未提交,普通代码慎用) 典型写法是:
__except(GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
,但生产环境更建议统一走
EXCEPTION_CONTINUE_SEARCH
,再靠全局过滤器兜底。 C知道 CSDN推出的一款AI技术问答工具 下载 SetUnhandledExceptionFilter 是更可靠的兜底方案 相比分散的
__try
/
__except
,注册全局异常过滤器更实用: 它能捕获所有未被任何
__try
/
__except
拦下的 SEH 异常 支持在崩溃瞬间调用
MiniDumpWriteDump
生成 dmp 文件,供 WinDbg 分析 可在 handler 中调用
ExitProcess
或弹窗提示,避免黑屏退出 关键点:
SetUnhandledExceptionFilter
必须在程序启动早期(如
main
或
WinMain
开头)调用,且仅对当前线程有效;多线程程序需为每个线程单独设置(或改用
SetThreadExceptionFilter
,但 Vista+ 才支持)。 混合使用 SEH 和 C++ 异常的风险点 当 C++ 代码同时启用
/EHsc
(标准异常)和 SEH(
/EHa
)时,编译器行为会变得不可预测: 局部对象析构可能部分执行,也可能跳过——取决于异常类型和展开路径
__finally
块在 C++ 异常传播中不一定执行(它只响应 SEH 展开) 第三方库若内部抛 C++ 异常,而你用
__except
捕获,
GetExceptionCode()
返回的是
STATUS_CPP_EXCEPTION
,不是
EXCEPTION_ACCESS_VIOLATION
,容易误判 真正体面的崩溃处理,从来不是靠“恢复执行”,而是快速记录上下文(线程 ID、寄存器、堆栈)、保存 dump、释放关键资源(如临时文件、独占句柄)、再干净退出。SEH 是手段,不是目的;别指望它把崩溃变正常。

相关文章