Visual C++中的异常处理浅析 - 结构化异常处理

结构化异常处理

  结构化异常处理(Structured Exception Handling,简称SEH)是微软针对Windows程序异常处理进行的扩展,在Visual C++中,它同时支持C和C++语言。SEH不宜与标准C++异常处理和MFC异常处理混用,对于C++程序,微软建议使用标准C++的异常处理。

  为了支持SEH,Visual C++中定义了四个关键字(由于这些关键字是非标准关键字,其它编译器不一定支持),用以扩展C 和C++语言:

  (1)__except

  (2)__finally

  (3)__leave

  (4)__try

  其基本语法为:

__try
{
...//可能导致异常的被监控代码块
}
__except(filter-expression)
{
...//异常处理函数
}


  或:

__try
{
...
}
__finally
{
...//终止
}


  其执行的步骤如下:

  (1)__try块被执行;

  (2)如果__try块没有出现异常,则执行到__except块之后;否则,执行到__except块,根据filter-expression的值决定异常处理方法:

  a. filter-expression的值为EXCEPTION_CONTINUE_EXECUTION (-1)

  恢复异常,从发生异常处下面开始执行,异常处理函数本身不被执行;

  b. filter-expression的值为EXCEPTION_CONTINUE_SEARCH (0)

  异常不被识别,拒绝捕获异常,继续搜索下一个异常处理函数;

  c. filter-expression的值为EXCEPTION_EXECUTE_HANDLER (1)

  异常被识别,终止异常,从异常发生处开始退栈,一路上遇到的终止函数都被执行。

  看看这个例子:

//例4-1
#include "stdio.h"

void main()
{
 int* p = NULL; // 定义一个空指针
 puts("SEH begin");
 __try
 {
  puts("in try");
  __try
  {
   puts("in try");
   *p = 0; // 引发一个内存访问异常
  }
  __finally
  {
   puts("in finally");
  }
 }
 __except(puts("in filter"), 1)
 {
  puts("in except");
 }
 puts("SEH end");
}


  程序的输出为:

SEH begin
in try //执行__try块
in try //执行嵌入的__try块
in filter //执行filter-expression,返回EXCEPTION_EXECUTE_HANDLER
in finally //展开嵌入的__finally
in except //执行对应的__except块
SEH end //处理完毕


  如果我们把__except(puts("in filter"), 1)改为__except(puts("in filter"), 0),程序的输出将变为:

SEH begin
in try //执行__try块
in try //执行嵌入的__try块
in filter //执行filter-expression,返回EXCEPTION_CONTINUE_SEARCH
in finally //展开嵌入的__finally


  程序的执行也告崩溃,弹出如图3所示的对话框。


图3 不能被正确执行的SEH


  要想这个程序能正确地执行,我们可以在第一个__try块的外面再套一个__try块和一个接收filter-expression返回值为EXCEPTION_EXECUTE_HANDLER的__except块,程序改为:

//例4-2
#include "stdio.h"

void main()
{
 int* p = NULL; // 定义一个空指针
 puts("SEH begin");
 __try
 {
  __try
  {
   puts("in try");
   __try
   {
    puts("in try");
    *p = 0; // 引发一个内存访问异常
   }
   __finally
   {
    puts("in finally");
   }
  }
  __except(puts("in filter"), 0)
  {
   puts("in except");
  }
 }
 __except(puts("in filter"), 1)
 {
  puts("in except");
 }
 puts("SEH end");
}


  程序输出:

SEH begin
in try //执行__try块
in try //执行嵌入的__try块
in filter1 //执行filter-expression,返回EXCEPTION_CONTINUE_SEARCH
in filter2 //执行filter-expression,返回EXCEPTION_EXECUTE_HANDLER
in finally //展开嵌入的__finally
in except2 //执行对应的__except块
SEH end //处理完毕


  由此可以看出,因为第一个__except的filter-expression返回EXCEPTION_CONTINUE_SEARCH 的原因,"in except1"没有被输出。程序之所以没有崩溃,是因为最终碰到了接收EXCEPTION_EXECUTE_HANDLER的第2个__except。

  SEH使用复杂的地方在于较难控制异常处理的流动方向,弄不好程序就"挂"了。如果把例4-1中的__except(puts("in filter"), 1)改为__except(puts("in filter"), -1),程序会进入一个死循环,输出:

SEH begin
in try //执行__try块
in try //执行嵌入的__try块
in filter //执行filter-expression,返回EXCEPTION_CONTINUE_EXECUTION
in filter
in filter
in filter
in filter
…//疯狂输出"in filter"


  最后疯狂地输出"in filter",我们把断点设置在__except(puts("in filter"), -1)语句之前,按F5会不断进入此断点。

  5.各种异常处理的对比

  下表给出了从各个方面对这本文所给出的Visual C++所支持的四种异常处理进行的对比:

异常处理支持语言 是否标准复杂度 推荐使用
C异常处理C语言标准C 简单推荐
C++异常处理C++语言标准C++较简单 推荐
MFC异常处理C++语言仅针对MFC程序较简单不推荐
SEH异常处理C和C++语言仅针对Microsoft编译环境较复杂不推荐


  本文所讲解的仅仅是Visual C++异常处理的初步知识,对于更深入的内容,还需要我们在不断的编程过程中去领悟和学习。

  在程序设计过程中,我们不能嫌异常处理"麻烦",对可能的错误视而不见、不加考虑。因为避免了异常处理的"麻烦",将会给我们的程序带来更大的"麻烦"。而程序中包含必要的异常处理,也是对一位优秀程序员的基本要求。

 

http://dev.yesky.com/115/2158115_4.shtml

 

 

以下还有一些要注意的问题,从网上找来的:

 

cannot use __try in functions that require object unwinding

With /GX, a function with structured exception handling cannot have objects that require unwinding (destruction).

Possible solutions

Move code that requires SEH to another function.

Rewrite functions that use SEH to avoid the use of local variables and parameters that have destructors. Do not use SEH in constructors or destructors.

Compile using /GX-. 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值