在Windows操作系统的C++程序开发中,结构化异常处理(SEH)是系统提供的一套原生异常处理机制,能够在程序发生内存访问错误、除零错误等异常时,优先捕获异常并执行预设的处理逻辑,避免程序直接终止,也可以帮助开发者收集崩溃现场信息用于后续排查问题。

SEH的基本原理
SEH是Windows操作系统层面的异常处理框架,和C++标准中的try-catch异常机制不同,它不依赖C++运行时,能够捕获系统级别的所有异常,包括硬件异常和软件异常。SEH的处理流程是基于线程的异常链实现的,每个线程都有自己的异常回调链表,当异常发生时,系统会依次调用链表中的回调函数,直到有处理函数处理了该异常或者程序终止。
C++中使用SEH的基础语法
在MSVC编译器中,提供了__try、__except、__finally三个关键字来支持SEH,语法和C++的try-catch类似,但是功能更偏向系统级异常处理。其中__try块中放可能触发异常的代码,__except块放异常处理逻辑,__finally块中的代码无论是否发生异常都会执行。
__except后面的括号中需要返回一个过滤表达式,可选的返回值有三个:
- EXCEPTION_EXECUTE_HANDLER:表示当前
__except块会处理该异常,执行块内逻辑后程序继续运行 - EXCEPTION_CONTINUE_SEARCH:表示当前
__except不处理该异常,系统会继续查找下一个异常处理函数 - EXCEPTION_CONTINUE_EXECUTION:表示系统会重新执行触发异常的指令,通常用于修复异常后恢复执行
捕获程序崩溃的示例代码
下面是一个简单的示例,演示如何使用SEH捕获除零错误和内存访问错误这两种常见的程序崩溃场景:
#include <windows.h>
#include <stdio.h>
// 异常处理过滤函数
LONG WINAPI ExceptionFilter(EXCEPTION_POINTERS* ExceptionInfo) {
// 获取异常代码
DWORD exceptionCode = ExceptionInfo->ExceptionRecord->ExceptionCode;
printf("捕获到异常,异常代码:0x%Xn", exceptionCode);
// 可以根据异常代码做不同的处理,这里直接返回继续执行处理
return EXCEPTION_EXECUTE_HANDLER;
}
int main() {
// 设置全局异常过滤函数
SetUnhandledExceptionFilter(ExceptionFilter);
__try {
// 模拟除零错误
int a = 10;
int b = 0;
int c = a / b;
printf("计算结果:%dn", c);
} __except(EXCEPTION_EXECUTE_HANDLER) {
printf("__except块处理了除零异常n");
}
__try {
// 模拟内存访问错误
int* p = NULL;
*p = 10;
} __except(EXCEPTION_EXECUTE_HANDLER) {
printf("__except块处理了内存访问异常n");
}
// __finally块无论是否异常都会执行
__try {
printf("进入__try块n");
// 触发异常
int* q = NULL;
*q = 20;
} __finally {
printf("__finally块执行,清理资源n");
}
return 0;
}
SEH的注意事项
在使用SEH时需要注意以下几点:
- SEH是MSVC编译器特有的扩展,在其他编译器如GCC、Clang中并不支持,所以如果程序需要跨平台,不建议依赖SEH实现核心异常处理逻辑
__try块中不能包含C++的对象构造和析构逻辑,否则会导致未定义行为,因为SEH不感知C++对象的生命周期,无法正确触发析构函数- 全局的
SetUnhandledExceptionFilter函数可以捕获没有被__try-__except处理的异常,适合作为程序最后的崩溃兜底处理,比如生成崩溃转储文件 - 不要滥用
EXCEPTION_CONTINUE_EXECUTION返回值,除非你确实修复了触发异常的问题,否则会导致程序陷入死循环反复触发同一个异常
SEH和C++标准异常的区别
很多开发者会混淆SEH和C++标准的try-catch异常,两者的核心区别如下:
| 对比项 | SEH | C++标准异常 |
|---|---|---|
| 所属层级 | Windows系统级 | C++语言标准级 |
| 捕获范围 | 所有系统异常,包括硬件异常、软件异常 | 仅捕获通过throw抛出的C++异常 |
| 编译器依赖 | 仅MSVC支持 | 所有符合C++标准的编译器都支持 |
| 对象析构 | 无法正确触发C++对象析构 | 可以正确触发栈上对象的析构函数 |
实际开发中可以根据场景选择使用,如果是Windows平台需要捕获系统级崩溃,优先使用SEH;如果是业务逻辑中的错误处理,优先使用C++标准异常。
SEH结构化异常处理C++Windows程序崩溃异常捕获修改时间:2026-07-01 12:06:28