zoukankan      html  css  js  c++  java
  • Visual C++中的异常处理浅析(5)

    4.结构化异常处理

      结构化异常处理(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++异常处理的初步知识,对于更深入的内容,还需要我们在不断的编程过程中去领悟和学习。

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

    上一页  [1] [2] [3] [4] [5] 

  • 相关阅读:
    zabbix:以主动模式添加一台受监控主机 (zabbix5.0)
    linux(centos8):用grep命令查找文件内容
    zabbix安装中文语言包及中文乱码的解决(zabbix5.0)
    性能测试常用术语
    Java 读写Properties配置文件
    携程Apollo配置中心架构深度剖析
    jmeter 使用csv文件 注意项
    CnPlugin_1.5.1 解决win10 pl/sql 输入法卡顿 兼容性问题
    jmeter(psot) 表单提交 注意项
    全新OCR3500数据
  • 原文地址:https://www.cnblogs.com/adylee/p/1233069.html
Copyright © 2011-2022 走看看