现在的位置: 首页 > 综合 > 正文

Windows异常处理

2013年09月13日 ⁄ 综合 ⁄ 共 2131字 ⁄ 字号 评论关闭

         前言:Windows系统级的异常处理SHE(结构化异常处理)是超越语言的,本文简单介绍在程序中如果使用。

1、          基本的异常处理形式

try-except块或try-finally块:

__try

{

    //程序代码

}

__finally

{

    //这里的代码总是被执行,甚至应用程序因为异常而退出的情形。

}

 

或者:

__try

{

    //程序代码

}

__except(exception)

{

    //这里的代码只有当__try块中有异常发生时才被执行。

}

        

一个__try块只能跟 __except__finally中的一个,而不能两个块都有。try-except块和try-finally块都可以嵌套。

2、          __except()中参数意义

__except()中的值exception可以是以下三个值.意义如下:

EXCEPTION_EXECUTE_HANDLER:            代码执行__except块中的代码.

EXCEPTION_CONTINUE_EXECUTION:     程序试图重新执行引发异常的代码,因为exception可以用一个函数代替,函数的返回值就是exception的值,所以可以在函数中进行一些操作使用原语句可以正确执行,但是并不推荐这样做.

EXCEPTION_CONTINUE_SEARCH:     表示继续搜索上一个异常过滤器,由上一级来处理.

        

看下面这个例子:

int GetException(int* i)

{

    if(*i==0)

    {

         *i = 1;

         return EXCEPTION_CONTINUE_EXECUTION;

    }

    else

       return EXCEPTION_EXECUTE_HANDLER;

}

int main()

{

     int a,b = 2,c = 0;

     __try

    {

      a = b / c;

    }

    __except(GetException(&c))

    {

        a = 3;

    }

    return a;

}

 

当这个程序被执行时,因为c的值是0,会引发一个异常,于是GetException函数被调用,结果是c被赋值为1,函数返回 EXCEPTION_CONTINUE_EXECUTION,于是程序试图重新计算a的值,我们期望的值是2/1=2,于是,main返回2,应用程序正常退出。但是如果真的编译这段代码,你得到结果可能是2也可能是3.也就是说1并没有被赋给c,原因就是c已经在CPU的寄存器当中,函数 GetException并不能改变寄存器中的值,所以再次引发异常,但是在调用GetException代码中c的值是1,所以返回 EXCEPTION_EXECUTE_HANDLER,于是__except块中的代码被执行.这就是为什么不推荐使用 EXCEPTION_CONTINUE_EXECUTION的原因.

3、          讨论

a)       BOOL AbnormalTermination()函数只在__finally块中调用,用来确定__try是自然退出还是出现异常退出.异常退出包括 goto,continue,break,return等退出形式.正常退出函数返回0,否则返回1.因为引发异常会有系统开销,所以如果想正常的终止 __try块中的代码,可以使用__leave关键字.它将使代码跳到__try的结尾执行(进入__finally块或跳出异常过滤器).

b)       异常处理有一个术语叫做全局展开,因为异常过滤器实质上是可以嵌套的,全局展开的意思就是直到找到一个地方,会处理引发的异常,才停止查找.如果一个异常没有被处理就称作一个未处理的异常,你在调试程序的时候可能常常会看到这个提示._finally中的return语句会终止这种查找.

c)       DWORD GetExceptionCode()函数在__except中使用(参数或者块中),函数返回异常的代码,代表引发异常的类型.GetExceptionInformation函数返回更详细的异常信息.

d)       异常也可以被主动的引发,C++中的throw关键字实际上在内部调用了函数RaiseException.这个函数用于引发一个异常.

e)       对于未处理的异常,操作系统在内部调用UnhandledExceptionFilter函数,我们可以通过 SetUnhandledExceptionFilter函数来设置异常发生时系统调用我们自己的函数,它的参数就是一个 UnhandledExceptionFilter形式的函数.如果想让系统重新调用UnhandledExceptionFilter函数,设置 SetUnhandledExceptionFilter的参数为0. 另外UnhandledExceptionFilter函数也可以由应用程序调用.

f)        异常处理只处理当前线程的异常,也就是说,如果在__try块中生成了新的进程或线程,而这些进程和线程中的异常,是不会被这个__try块处理的.

抱歉!评论已关闭.