[读书笔记] 关于Windows的结构化异常处理SEH(二)

上篇说的是终止处理程序,这篇接着看异常处理。

也就是:

<pre name="code" class="cpp">__try
{
	// 被保护的代码
}
__except(exception filter/*异常过滤程序*/)
{
	// 异常处理程序
}

 与终止处理程序不同,异常过滤程序与异常处理程序主要是操作系统负责执行的,另外,在try块中的return,goto等语句不会导致像在终止处理程序中的那种局部展开,所以不会有额外的开销,其实很好理解,异常过滤程序和异常处理程序只是在try块发生异常才执行,而return之类的语句通常不会引发异常。 


*异常过滤程序

如果try块中的代码出现被0的情况,CPU会捕获这个时间,并抛出一个硬件异常(后面的文章会说到软件异常),系统定位到except块的开始处,这时,就会执行异常过滤程序,也就是对except括号中的表达式求值,这个表达式的值可能有3种:

EXCEPTION_EXECUTE_HANDLER: [except对操作系统说:我的{}中是异常处理程序,请执行,执行完毕后请跳到我的{}后面去接着执行后面的代码]

  简单来说就是相当于告诉系统,我知道这个异常,而且我也写了处理这个异常的代码,现在我要执行这些代码。于是,系统执行全局展开,然后跳转到异常处理程序中执行,在异常处理程序执行完毕后会接着执行except后面的代码,就想异常没有发生一样,其实这个标记就意味着告诉系统,一切都在掌控中,有问题我自己有代码会处理,请继续运行就好了。

另:从Vista开始,如果一个异常发生在try/finally中,并在其上层没有try/except块(而且这个块的过滤程序返回EXEPTION_EXCUTE_HANDLER),进程就会立刻终止,全局展开不会发生,当然finally块也就不会被执行。

EXCEPTION_CONTINUE_EXECUTION:[except对操作系统说:我的{}中是异常处理程序,请执行,但是执行完毕后请跳回刚才发生异常的语句重新从那里执行]

这个标记的特点是,在except执行完毕后会调回异常发生的代码重新执行一遍原来产生异常的代码,这个特点就好像系统给你一个纠错的权利,但是需要谨慎使用这个权利,通常正确的程序设计是在程序发生异常后要通知开发者,而不是用一些预定的代码去试图修复异常,这样只会把问题隐藏起来,还有一个很重要的原因是,一句c++代码可能被翻译成很多条汇编指令,仅仅从产生异常的那句汇编指令重新执行往往不但不能修复异常,反而容易让程序进入异常死循环。

EXCEPTION_EXCUTE_SEARCH:[except对操作系统说:我不处理异常,你去找我老大(外层的except)]

顾名思义,这个标记会通知系统让系统在调用栈中向上查找前一个except块的异常过滤程序并执行,而返回EXCEPTION_EXCUTE_SEARCH标记的except块中的代码永远没有机会执行。

决定返回什么标记前,显然要先知道是什么类型的异常,这可以在异常过滤程序中调用GetExceptionCode来确定,此函数返回发生了哪类异常,当然此函数也只能在异常过滤程序中调用,也就是except后面的括号内。


上面说的异常都是指硬件异常,也就是由cpu捕获事件而抛出的异常,我们也可以在应用程序代码中主动抛出一个异常,也就是软件异常,使用RaiseException函数(c++的throw应该最终也是调用的这个函数)


总结,这篇最关键的就是异常过滤程序返回的这三个标记,他们会导致系统的控制行为不同。高级语言都有自己的异常处理体系,不过在windows上他们还是通过SEH实现的。


end.

第一遍读这几章,理解有误处欢迎指正。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值