Visual C++异常处理机制原理与应用(三)——C/C++结构化异常处理之try-except异常处理的使用(上)

来源:互联网 发布:pdf.js ajax 编辑:程序博客网 时间:2024/05/18 19:44

在微软的VC++中,C/C++结构化异常处理机制一共包含两部分内容:终止处理程序和异常处理程序。

其中,终止处理程序的使用与原理已经在《Visual C++异常处理机制原理与应用(一)—— C/C++结构化异常处理之try-finally终止处理的使用与原理(上)》和《Visual C++异常处理机制原理与应用(二)—— C/C++结构化异常处理之try-finally终止处理的使用与原理(下)》文章中介绍过了(其中还差全局展开和系统全局展开的原理分析留到后面进行)。这里介绍VC中C/C++结构化异常处理中的另一部分——异常处理程序。

在实际的开发中,我们常希望有如下功能:如果程序执行过程中发生异常情况,则转而执行一段特定的处理代码,比如试图对异常进行修复,或者在提示用户程序遇到问题需要关闭以及发送错误报告等操作后,优雅地退出。这种需求可以抽象概括如下:

  1. 如果程序正常执行,则异常处理代码不执行
  2. 如果程序发生异常,则执行异常处理代码

为了满足这种需求,在VC中,C/C++结构化异常处理的异常处理应运而生:

__try{    // 可能出现异常的代码}__except(异常过滤函数){    // 发生异常后的处理代码}

异常过滤函数的返回值决定了异常发生后程序的执行流程。为此,VC++中预定义了如下几个宏:

#define EXCEPTION_EXECUTE_HANDLER      1    // 执行__except后的异常处理代码#define EXCEPTION_CONTINUE_SEARCH      0    // 本异常处理块不对该异常进行处理,继续找外围的处理块#define EXCEPTION_CONTINUE_EXECUTION (-1)   // 重新执行出错的语句
  1. 如果__try块中的代码未发生异常,则其中的代码执行完成后,直接转到本异常处理块后的代码继续执行。__except块中的代码不执行。
  2. 如果发生了异常且本块能够处理:
    1. 首先查看内层有无try-finally块,如果有则先执行finally块的代码。如果内层有多个try-finally块,则从最内层开始执行。
    2. 如果内层没有try-finally块或已执行完了所有的finally块,则执行本except块中的内容。注意:如果return语句在finally块中,则执行后不再执行后续的finally块以及本except块(即3中的步骤也没了)。
    3. 执行流程转入到__except块中,执行完毕后继续执行本异常处理块后的代码。
  3. 如果发生了异常且本块不处理,则程序执行流转入到外围的异常处理块中,且执行完后执行的是外围能处理该异常的处理块后的代码。

此外,需要注意的是:

  • 当返回EXCEPTION_CONTINUE_EXECUTION时,表明在过滤表达式中已经对异常进行修正,可以继续执行刚才发生异常时的语句了。但这种修正很可能不成功,如果编译器生成的是下述指令,则即便是在过滤函数中将pszBuff修正到合法地址后,继续执行出错的汇编指令时,由于eax寄存器的值依然为0,所以还是会出错。因此,由于发生处的上下文环境不确定,所以最好谨慎地使用EXCEPTION_CONTINUE_EXECUTION
char *pszBuff = NULL;//...*pszBuff = 'v';// mov eax, [pszBuff]// mov byte ptr [eax], 'v'
  • 在try-except异常处理程序中,应该只处理那些我们确定能解决的异常。否则盲目地捕获异常并且当做什么也没发生过,其实有可能造成程序运行在一种危险状态中而不自知。

  • 在try-except异常处理程序中使用控制流程提前转移的语句不会造成局部展开,因此不会像try-finally型异常处理程序那样产生性能问题。

阅读全文
0 0
原创粉丝点击