条目1、促使微软将SEH加入WINDOWS系统的因素之一是它可以简化操作系统本身的开发工作。(P621)
条目2、终止处理的语法(P622)
操作系统和编译器协同工作保证不管被保护的代码如何退出(return、goto、longjmp)的,终止处理程序都会被调用。即__finally代码块都能执行。(P622)
条目3、局部展开就是为了在try代码块非正常离开前,能够执行finally块而所做的工作。(P624)
我们应该避免在try语句中使用能让try语句块提前结束(跳过)的语句,因为这样会损害应用程序的性能。代码控制流正常地离开try代码块进入finally代码块时,性能开销最小。
验证:
(1) 编写正常离开try块的示例代码
(2) 编译后,反汇编其内容
我们很清楚的看到,当控制流正常离开try进入finally时,整体编译出来的代码比较精简、流畅,性能开销小(00401055处直接调用finally中的代码)。
(3) 编写非正常离开try块的示例代码
(4) 编译后,反汇编其内容
当控制流非正常离开try进入finally时,系统进行局部展开(0040105F call __local_unwind4),经过层层处理后在内部执行finally代码块。很明显,此时性能开销比较大。
条目4、从WINDOWS VISTA系统开始,须显式地保护try/finally框架,以确保在异常抛出时,finally代码块会执行。(P625)
条目5、终止处理程序(finally)同样可以捕获setjmp/longjmp、break、continue、goto等语句。(P626)
示例代码:
结果是:14
条目6、在进程或线程被提前终止的情况下,系统没办法保证finally代码块会被执行。换句话说,在try块中调用ExitProcess或ExitThread将不会导致finally代码块的执行。一个线程或进程被其他程序调用TerminateThread或TerminateProcess终止时,也不会导致finally代码块的执行。(P627)
条目7、关键字__leave会导致代码执行控制流跳转到try块的结尾,使代码以正常的方式从try块进入finally块中。(P631)
条目8、总结引起finally块执行的三个原因:
(1) 从try块到finally块的正常代码控制流
(2) 局部展开(从try块中提前退出进入finally块,由goto/longjmp/continue/break/return等语句引起)
(3) 全局展开
注意:在WINDOWS VISTA系统上,全局展开在默认的情况下是不会被触发的,所以finally不会被执行。调用AbnormalTermination宏可以确定与当前finally块相关的try快是否提前退出。AbnormalTermination宏只能在finally块中被调用。