Windows提供的结构化异常处理(SEH)
1.结束处理主要是由编译器来实现,异常处理操作系统实现的要多一些
2.当异常块出现时,编译器要生成特殊的代码,并且生成一些表结构来处理SEH,另外还要生成
一些回调函数
3.SEH与C++的异常处理不同
一、结束处理
1.使用形式
_try
{
//processing
}
_finally
{
//主要是一些后处理、内存回收、Release等
}
2.当以下三种情况发生时,进入_finally
a. _try块代码自然执行完成
b. _try块中调用return,goto,longjump,break等导致跳出_try块时
c. _try块代码执行中由于调用其他函数发生异常,书中把这个叫做全局展开(global unwind)
注意,当调用exitthread exitprocess terminatethread terminateprocess时,不进入finally
3.编译器如何实现
_try块中查找可能导致跳出的return、goto等语句,发现后,将finally函数在该处展开。
将会导致编译时的时间开销变大
4.个人感觉
如果你担心由于异常会使程序中的一些该释放的资源没有释放,则可以试一试
其他感觉用处不是很大,书中所举结束处理使代码可读性增强的例子,说服力不强
二、异常处理
1. 使用形式
_try
{
//processing
}
_except(EXCEPTION_EXECUTE_HANDLER) //也可以是EXCEPTION_CONTINUE_SEARCH或者EXCEPTION_CONTINUE_EXECUTE
{
//对异常的处理
}
2 过滤器的三种条件分别表示
EXCEPTION_EXECUTE_HANDLER:执行except块,执行完except块以后,接着执行except块之后的代码,而不会返回到出现异常的代码
EXCEPTION_CONTINUE_SEARCH:搜索更高层的except进行执行
EXCEPTION_CONTINUE_EXECUTE:继续执行
3 全局展开
确定了一个出现异常后,如何寻找相应的finally和except的流程
基本规则是先内后外,再从外到内,最后由内而外,是不是晕了哦
先执行finally,后finally
4 GetExceptionCode
DWORD GetExceptionCode(VOID);
有10几种异常,感兴趣msdn之
5 软件异常
也就是自己通过调用函数报告异常
RaiseException
VOID RaiseException(
DWORD dwExceptionCode, // exception code
DWORD dwExceptionFlags, // continuable exception flag
DWORD nNumberOfArguments, // number of arguments
CONST ULONG_PTR *lpArguments // array of arguments
);
三、未处理异常和C++异常
1 UnhandledExceptionFilter
LONG UnhandledExceptionFilter(
STRUCT _EXCEPTION_POINTERS *ExceptionInfo
);
主要功能:弹出一个对话框,该对话框对出现的异常进行了一些描述,提示用户是否要进行调试。
如果选择终结该进程,则执行except块,否则调用调试程序,调试程序attach到当前进程,开始进行调试
这样的对话框大家估计都见过,反正程序出现问题的时候经常会看到
2 使用形式
实际主要用在函数basethreadstart和baseprocessthread两个函数上
这两个函数是createthread或createprocess后,创建完线程堆栈,初始化完成线程内核对象和contex结构后,IP所指向的函数
也就是线程执行时调用的第一个函数
他的定义大概是这样的
void basethreadstart(pfnstartaddr, pvParam)
{
_try
{
ExitThread((pfnstartaddr)(pvParam)));
}
_except(UnhandledExceptionFilter(GetExceptionInformation()))
{
ExitProcess(GetExceptionCode());
}
}
所以很多程序错误是弹这个框框也就不足为怪了
另外,如果内核模式出现了未处理的C++异常时,机器直接蓝屏,呵呵
3 与C++异常机制的比较
书中提到,VC++中,C++的异常处理实际上是用_try和_except实现的
SEH C++
_try try
_except catch
RaiseException throw
有几点不同
a. c代码中不能用c++这套机制
b. SEH中提供的功能还是要更强大一些
c. 个人觉得C++还是用自己的异常处理机制比较好