windows 结构化异常处理包括了2个方面:终止处理和异常处理. 本文讨论终止处理
1.终止处理程序
基本语法:
__try
{
//可能会发生异常的代码部分
}
__finally
{
//终止处理
}
在这段代码中,在编译器和操作系统协同下,try中发生异常,return,goto等非强制退出(即ExitProcess,TermainateProcess等方式退出),
__finally中的代码都会执行.
测试代码:
int main() { int b; char c = 'a'; __try { b = 3 /(c-97);//除0异常 } __finally { printf("finally "); } return 0; }
结果:
此时还未输出,点击取消时将:
后来才发现将生成模式改为release就不会弹出系统提示而直接输出finally. 所以要很好的利用seh 应该采用release模式生成项目
将除0代码改为return语句结果是直接输出finally
2.异常处理程序
代码结构:
__try
{
}
__except( //filter code)
{
}
过滤code只可以是
EXCEPTION_EXECUTE_HANDLER 1 :开始进行全局展开,执行异常处理代码,完了后继续执行except的后续代码
EXCEPTION_CONTINUE_SEARCH 0 ; 寻找外面一层try代码块
EXCEPTION_CONTINUE_EXECUTION -1 ;继续执行导致异常的那条代码
全局展开:
测试代码:
// seh2.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include <windows.h> void f1() { int a; char b = 'a'; __try { a = b / (b - 97);//2
//不执行 } __finally { printf("f1 ");//4 } } int main() { __try { f1(); //1 printf("main's try "); } __except (EXCEPTION_EXECUTE_HANDLER)//3 { printf("main ");//5 } printf("over"); //6 return 0; }
执行结果:
代码中数字为序号. 即当子函数中发生异常时会向外寻找except, 如果异常过滤程序返回EXCEPTION_EXECUTE_HANDLER 则进行全局展开
回去执行完finally后再执行except的异常处理函数,最后执行except后面的代码
3.GetExceptionInformation
当异常发生时将对目标线程压入3个结构的地址:
EXCEPTION_RECORD, CONTEXT(线程上下文) , EXCEPTION_POINTERS
typedef struct _EXCEPTION_RECORD {
DWORD ExceptionCode;
DWORD ExceptionFlags;
struct _EXCEPTION_RECORD *ExceptionRecord;
PVOID ExceptionAddress;
DWORD NumberParameters;
ULONG_PTR ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS];
} EXCEPTION_RECORD;
typedef struct _EXCEPTION_POINTERS {
PEXCEPTION_RECORD ExceptionRecord;
PCONTEXT ContextRecord;
} EXCEPTION_POINTERS, *PEXCEPTION_POINTERS;
而
(struct _EXCEPTION_POINTERS*) GetExceptionInformation()
可以获取这些参数. 该函数只能在异常过滤函数中使用.