SEH的EXCEPTION_CONTINUE_EXECUTION

因为工作需要,又要研究一下C++的Exception机制,用MSVC的话,自然又要了解一下Windows的Standard Exception Handling(简称SEH,不是SHE),实际上MSVC的Exception机制就是基于SEH的。
 
在这个链接( http://51cmm.csai.cn/ExpertEyes/No159.htm)上,介绍了一下SEH在VC中的体现,就是__try/__except关键字,在__excep后面的()中是一个表达式,值可以是
EXCEPTION_CONTINUE_EXECUTION (–1) 异常被忽略,控制流将在异常出现的点之后,继续恢复运行。
EXCEPTION_CONTINUE_SEARCH (0) 异常不被识别,也即当前的这个__except模块不是这个异常错误所对应的正确的异常处理模块。系统将继续到上一层的try-except域中继续查找一个恰当的__except模块。
EXCEPTION_EXECUTE_HANDLER (1) 异常已经被识别,也即当前的这个异常错误,系统已经找到了并能够确认,这个__except模块就是正确的异常处理模块。控制流将进入到__except模块中。

 
文中还举了一个使用EXCEPTION_CONTINUE_EXECUTION的例子,如下
  1. #include <stdio.h>
  2. void main()
  3. {
  4.    int j, zero;
  5.    puts("hello");
  6.    __try
  7.    {
  8.         puts("main()函数的try块中");
  9.         zero = 0;
  10.         j = 10;
  11.         // 下面将导致一个异常 
  12.         j = 45 / zero; 
  13.         // 注意,异常出现后,程序控制流又恢复到了这里
  14.         printf("这里会执行到吗?值有如何呢?j=%d /n", j);
  15.    }
  16.    // 注意,这里把zero变量赋值为1,试图恢复错误,
  17.    // 当控制流恢复到原来异常点时,避免了异常的再次发生
  18.    __except(puts("in filter"), zero = 1, -1)
  19.    {
  20.        puts("main()函数的except块中");
  21.    }
  22.    puts("world");
  23. }
上面的程序运行结果如下:
hello
main()函数的try块中
in filter
这里会执行到吗?值有如何呢?j=45
world
Press any key to continue
 
也许在原作者的开发环境下,的确是这个结果,但是......
 
这段程序想演示一个recover exception的技巧,在C/C++中,用逗号串起来的表达式还是一个表达式,这个整体表达式的值是最后一个表达式的值,所以 puts("in filter"), zero = 1, -1的返回值是最后一个值(-1),也就是EXCEPTION_CONTINUE_EXECUTION,而之前的表达式也会被evaluate,也就是"in filter"会被打印,而且zero也会被赋为1,这样,在这个thread回去再次执行 j = 45 / zero;的时候,zero已经是1了,于是是不会再次有异常发生。真的是这样吗?不见得,在我的机器上,这段程序陷入一个死循环。
 
我用VS2005的Debug模式看了一下生成的汇编代码,发现问题所在了,zero的值一开始就被MOV到ECX中了,然后把45这个常数MOV到EAX中,然后IDIV EAX, ECX,再看__except部分的汇编代码,zero=1的汇编代码只是修改了表示zero的内存,并没有动ECX,这样__except在ignore这个exception之后,并不是直观上的回去执行“j=45/zero”这个C++语句,而是去执行“IDIV EAX,ECX”这条机器指令,而这时候ECX还是0,所以又是一个exception,陷入死循环!
 
从中需要加深几点意识:
1) __except(EXCEPTION_CONTINUE_EXECUTION)是让thread回到发生exception的机器指令,不是回到发生exception的C/C++语句;
2) 没有多少适合用__except(EXCEPTION_CONTINUE_EXECUTION)的场合,除非__try部分是用汇编写的。
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值