千言万语从何说起呢?嗯,还是先说说SEH的特点吧:
SEH的优点在于当你编写代码的时候,可以集中注意力完成任务,如果在运行的时候出现了问题,系统会捕获到错误并且通知你出了问题.
使得SEH工作的任务主要落在编译器而不是操作系统上.当进入,退出异常块时候,你的编译器必须产生特殊的代码.编译器必须产生处理SEH的数据结构,还必须提供操作系统能调用的回调函数来使得异常块能被遍历.编译器还负责准备栈框架何别的供操作系统使用和引用的内部信息.
不同厂家的编译器对实现SEH的方法也许不一样,但功能上大致是一样的,所以我们这里可以忽略SEH具体的实现细节.大多数厂家都遵循了Mircosoft建议的语法.
这里一定要记住:千万不用把SEH同C++的异常处理混淆.C++的异常处理是另外一种异常处理的形式,他使用C++中的try,catch和throw关键字.microsoft 在Visual C++ 2.0的时候加入了C++异常处理.关于C++的异常处理我想在下一篇文章来阐述.
(SEH)结构化异常处理中的关键字:
__try,__finally,__leave,__execept
(SEH)结构化异常处理的功能分类:
1终止处理程序,2异常过滤程序,3异常处理程序.,4软件异常.
下面就对这四种形式加以讨论.首先来看看终止处理程序.所谓的终止处理程序,是__try {} __finally{}块.他的microsoft
语法是:(以下如果没有特殊说明,指的都是mircosoft的语法)
__try
{
//Guaded body
...
}
__fianlly
{
// Termination handler
...
}
关键字 __try 和__finally描述终止处理程序的两个部分.在上面的代码中,操作系统和
编译器一起确保终止处理程序的中__finally代码块被执行,而不管被保护体__try是怎样退出的.
也就是就算你在__try中加如了return,goto,或者longjump,终止程序都会被执行.下面是代码执行的流程:
//1 先于__try块的代码被执行
__try{
//2 __try中的代码被执行
}
__finally{
//3 __fianlly中代码被执行
}
// 4 __fianlly后面的代码被执行.
也许这样的描述还不够清楚,是的,要了解SEH是如何工作的,最好的办法就是写段代码来测试一下:
DWORD Fun(void)
{
DWORD dwTemp;
// DO any thing u want here
__try
{
WaitForSingleObject(G_hSign,INFINITE);
dwTemp = 5;
return dwTemp;
}
__finally
{
ReleaseSemaphore(G_hSign,1,NULL);
}
dwTemp = 9;
return dwTemp;
}
也许你已经发现在__try中有一个return语句,如果__finally不被执行的话,那么信号量就不会释放,程序的流程
就出问题了.请记住SEH终止处理程序保证在__try中过早退出时,__finally中代码一定会被执行,然后才返回.
这被称为局部展开(local unwind)
如果真的想早点跳出__try 块,请使用__leave这个关键字。他的用法如下:
__try
{
// condition test
__leave;
//another conditon test
__leave;
//so on
}
__finally
{
//do some clean up job here
}
__leave关键字的含义是: 在__try中使用__leave关键字将导致一个到__try快末尾的跳转,而后进入到__finally 块。
__finally块中的代码被执行有三种可能性:
1 程序自然的从__try中进入__try.
2 从try块中过早的退出如使用了goto, longjump,continue,break,return等强迫控制转移到__finally块。
3 是全局展开,不用显式的表明,比如我们在__try 块中调用了一个函数,而这个函数引起了内存访问错误
那么__finally块中的代码也会被执行。如下面的代码
void Dofnc()
{
char* buffer = 0;
*buffer = 0x30;
}
__try
{
Dofnc(); //这个函数引起一个内存访问错误。
//其他的代码
}
__finally
{
//do clean up job here
}
BOOL AbnormalTermintion(void) 这个函数可以使我得知程序是正常进入还是异常(全局,局部)进入__finally块。
AbnormalTermintion返回TRUE 表示异常进入,FALSE表示正常进入__finally