Windows SEH之全局展开
这里说说SEH中让人费解的全局展开部分。在此之前先复习一下结构化异常处理的流程:
当异常过滤程序的计算结果为EXCEPTION_EXECUTE_HANDLER时,系统会执行全局展开。
下面这张图片展示了全局展开的流程图(对应上图中全局展开的部分):
当一个异常出现的时候,会从检查当前异常的try块是否可以处理该异常(也就是看看是不是有except块,且Filter的计算结果是否为EXCEPTION_EXECUTE_HANDLER),如果不可以则检查当前try块中是否有finally块,有则执行,然后沿着调用链向上查找(也就是看看上级函数中是否有try-except块可以处理该异常)。如果找到可以处理该异常的except块,则执行异常处理程序,执行结束后从异常处理程序的下一条语句开始继续运行。
示例分析一
下面来看一个例子:
#include<iostream>#include<Windows.h>intExceptionFilter(){std::cout<<"ExceptionFilter"<<std::endl;returnEXCEPTION_EXECUTE_HANDLER;}voidfuncA(){__try{std::cout<<"funcA try"<<std::endl;// exception*(PBYTE)NULL=5;std::cout<<"funcA try end"<<std::endl;}__except(ExceptionFilter()){std::cout<<"funcA ExceptionFilter"<<std::endl;}}voidfuncB(){__try{std::cout<<"funcB try"<<std::endl;funcA();std::cout<<"funcB try end"<<std::endl;}__finally{std::cout<<"funcB finally"<<std::endl;}}voidfuncC(){__try{std::cout<<"funcC try"<<std::endl;funcB();std::cout<<"funcC try end"<<std::endl;}__finally{std::cout<<"funcC finally"<<std::endl;}}intmain(intargc,charconst*argv[]){// C -> B -> AfuncC();return0;}运行结果如下:
示例分析二
#include<iostream>#include<Windows.h>intExceptionFilter(){std::cout<<"ExceptionFilter"<<std::endl;returnEXCEPTION_EXECUTE_HANDLER;}voidfuncA(){__try{std::cout<<"funcA try"<<std::endl;// exception*(PBYTE)NULL=5;std::cout<<"funcA try end"<<std::endl;}__finally{std::cout<<"funcA finally"<<std::endl;}}voidfuncB(){__try{std::cout<<"funcB try"<<std::endl;funcA();std::cout<<"funcB try end"<<std::endl;}__except(ExceptionFilter()){std::cout<<"funcB ExceptionFilter"<<std::endl;}}voidfuncC(){__try{std::cout<<"funcC try"<<std::endl;funcB();std::cout<<"funcC try end"<<std::endl;}__finally{std::cout<<"funcC finally"<<std::endl;}}intmain(intargc,charconst*argv[]){// C -> B -> AfuncC();return0;}运行结果如下: