对于 SEH 大家应该比较熟悉,但是当我们在写内核程序的时候,如何利用这种机制为我们的调试或者提高程序的健壮性作出自己的
贡献呢?
现在,我想对我自己掌握的这方面的东西做一个总结:
首先,我想回顾一下我们的程序在出现异常的时候,操作系统到底做了什么事情吧。。。
当我们的程序出现异常的时候,操作系统,首先会是扫描一下一个异常处理的容器(堆栈回溯,查找处理方法),
这个种结构,其实就是一个单项链表,
每一项都被封装在一个结构体中,如果我们定义有自己的异常处理机制,系统首先会在我们定义的机制中查找处理方法,
如果找到,就是用我们的方法来处理,否则,跳出,在系统定义的机制中查找,如果没有解决方案。。。
由于,我们是在 ring 0 运行,那就 OVER 了。。。
现在,我们知道了这种机制的运作后,我们就像利用这种机制服务我们。。。
在 C++ 中,我们有 try throw catch finally except 这几种关键字。。。
那么,现在,我们用的是 C 。那么,我们推荐使用 如__try、__finally、和__except。拥有下划线的,注意,这里和 C++不一样,在 C++编译单元中,try 语句必须与 catch 语句成对出现,这是一个完全不同的异常机制,是 C++ 语言的一部分。。。
现在,我们来使用的例子:
__try
{
<guarded body>
}
__finally
{
<termination handler> 无论如何 程序必须 这里的语句,如果在__try 中出现了异常,
程序只能执行__finally 中内容(无论是 return 还是 goto ),
然后就返回了,finally 外边后面的内容就不能执行了。。。
}
Try-Except块
__try
{
<guarded body> 这里如果有 return , goto,__leave 就跳过了堆栈的回朔
}
__except(<filter expression>)
{
<exception handler>
}
这种使用方法,和上边的区别在于,可以选择性的执行,为什么? 没看到 __except 中的参数吗?
一共有三个选项, filter expression == 1 :用我们定义好的异常机制处理; == 0 继续查找其他的处理方式,如果没有找到,OVER..
== -1 返回出现异常的定法继续执行。。。
EXCEPTION_EXECUTE_HANDLER 数值上等于 1
EXCEPTION_CONTINUE_SEARCH 数值上等于 0
EXCEPTION_CONTINUE_EXECUTION 数值上等于-1
__except 子句中的过滤表达式在每次异常发生时只求值一次。
那么,我们可以通过写一个函数判断他的返回值,决定使用我们自己的处理,还是继续查找其他的处理方法。
当然,也可以用逗号表达式的方法。。。
逗号操作符总是放弃它左边的表达式而对右边表达式求值。所以,最后一个表达式的值就是整个表达式的求值
结果。
具体可以套用这样:
__except(EvaluateException(GetExceptionCode(), GetExceptionInformation()))
LONG EvaluateException(NTSTATUS status, PEXCEPTION_POINTERS xp)
{
...
}
...
还有一些效率问题的细节:
__Leave 语句
Microsoft 在其 C/C++语言中加入了__leave 语句,它解决了文中 AddDevice 例程出现的效率问题。
如果在__try 块中发出一个普通的 return 语句,将触发昂贵的回卷机制。
然而,__leave 语句可以直接把控制传递到终止处理程序,最后到达终止处理程序后面的语句。
由于它不造成任何回卷动作,所以要比 return 语句快得多。
在这个例子中,我们总是执行终止处理程序并返回一个状态代码。
因为我们在代码执行成功或失败后都要执行相同的语句:return status,所以可以用__leave 代替 return。
__leave 跳过了 异常处理部分的代码,接着__except 外边的后边的代码执行。。。