Windows核心编程 第23章 结束处理程序

2 3章 结束处理程序

SEH(结构化异常处理)

    使用 S E H的好处就是当你编写程序时,只需要关注程序要完成的任务。

如果在运行时发生什么错误,系统会发现并将发生的问题通知你。利用S E H,你可以完全不用考虑代码里是不是有错误,这样就把主要的工作同错误处理分离开来。这样的分离,可以使你集中精力处理眼前的工作,而将可能发生的错误放在后面处理。

    S E H实际包含两个主要功能:结束处理( termination handling)和异常处理( e x c e p t i o nh a n d l i n g)。本章讨论结束处理,下一章讨论异常处理。

    注意:不要将结构化异常处理同C + +的异常处理相混淆。C + +异常处理是一种不同形

式的异常处理,其形式是使用C + +关键字c a t c ht h r o w。最后再区分这两个的区别。

下面是基本调用样子:

 

- - t r y- - f i n a l l y关键字用来标出结束处理程序两段代码的轮廓。在上面的代码段中,操作系统和编译程序共同来确保结束处理程序中的 - - f i n a l l y代码块能够被执行,不管保护体( t r y块)是如何退出的。不论你在保护体中使用 r e t u r n,还是g o t o,或者是l o n g j u m p,结束处理程序(f i n a l l y块)都将被调用。

要完成这些事情,编译程序必须生成附加的代码,系统要执行额外的工作。在不同的C P U上,结束处理所需要的步骤也不同。例如,在 A l p h a处理器上,必须执行几百个甚至几千个C P U指令来捕捉t r y块中的过早返回并调用f i n a l l y块。在编写代码时,就应该避免引起结束处理程序的t r y块中的过早退出,因为程序的性能会受到影响。

注意当控制流自然地离开t r y块并进入f i n a l l y块(就像在F u n c e n s t e i n 1中)时,进入f i n a l l y块的系统开销是最小的。在x86 CPU上使用微软的编译程序,当执行离开 try 块进入f i n a l l y块时,只有一个机器指令被执行。


常用举例:

1.


会弹出崩溃框,但是点击关闭后会执行finally代码,但是不会执行第二个messagebox:



2.下面这个函数返回14,自己好好理解下:


3.下面这个,按照书上的意思是返回2,然而是没编译过去(vs2012 C++)

 

4.书上写了三个函数,同功能,直接截图过来了

1


2


3


5.最终的边界

    为了帮助避免在t r y块中使用r e t u r n语句,微软在其C / C + +编译程序中增加了另一个关键字- -l e a v e。这里是F u n c a r m a 4版,它使用了- - l e a v e关键字:

 如果直接这样:

那么return导致的进入finally的状态不是流入的,也就是需要很多辅助代码来处理,如果直接使用__leave


那就是类似如下优化:


从而优化了执行时间。
关于f i n a l l y块的说明

已经明确区分了强制执行f i n a l l y块的两种情况:

• 从t r y块进入f i n a l l y块的正常控制流。

• 局部展开:从t r y块的过早退出(g o t ol o n g j u m pc o n t i n u eb r e a kr e t u r n等)强制控制转移到f i n a l l y块。

    第三种情况,全局展开( global unwind),在发生的时候没有明显的标识,我们在本章前面F u n c f u r t e r 1函数中已经见到。在F u n c f u r t e r 1t r y块中,有一个对F u n c i n a t o r函数的调用。如果F u n c i n a t o r函数引起一个内存访问违规( memory access violation),一个全局展开会使F u n c f u r t e r 1f i n a l l y块执行。下一章将详细讨论全局展开。

由于以上三种情况中某一种的结果而导致f i n a l l y块中的代码开始执行。为了确定是哪一种情况引起f i n a l l y块执行,可以调用内部函数(或内蕴函数,intrinsic functionAbnormal Te r m i n a t i o n

BOOL AbnormalTermination();

这个内部函数只在f i n a l l y块中调用,返回一个B o o l e a n值。指出与f i n a l l y块相结合的t r y块是否过早退出。换句话说,如果控制流离开 t r y块并自然进入f i n a l l y块,A b n o r m a l Te r m i n a t i o n将返回FA L S E。如果控制流非正常退出 t r y块 — 通常由于g o t or e t u r nb r e a kc o n t i n u e语句引起的局部展开,或由于内存访问违规或其他异常引起的全局展开 — 对A b n o r m a l Te r m i n a t i o n的调用将返回T R U E。没有办法区别f i n a l l y块的执行是由于全局展开还是由于局部展开。但这通常不会成为问题,因为可以避免编写执行局部展开的代码。

使用结束处理程序的理由:

• 简化错误处理,因所有的清理工作都在一个位置并且保证被执行。

• 提高程序的可读性。

• 使代码更容易维护。

• 如果使用得当,具有最小的系统开销。


Try__Try区别:

异常处理

 

结果是输出两个对话框,没有崩溃界面。


SEH


结果是先输出一个崩溃页面,点击关闭,弹出matk1对话框。


 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值