zoukankan      html  css  js  c++  java
  • C++异常处理的深入理解

    1,问题:

        1,如果在 main 函数中抛出异常会发生什么?

           1,不处理,则崩溃;

     

    2,如果异常不处理,最后会传到哪里?

     

       

    3,下面的代码输出什么?

     

    4,异常的最终处理编程实验:

     1 #include <iostream>
     2 
     3 using namespace std;
     4 
     5 class Test 
     6 {
     7 public:
     8     Test() 
     9     {
    10         cout << "Test()"; 
    11         cout << endl;
    12     }
    13     
    14     ~Test() 
    15     {
    16         cout << "~Test()"; 
    17         cout << endl;
    18     }
    19 };
    20 
    21 int main()
    22 {
    23     static Test t;  // BCC Test();
    24                 // VC 2010 Test();
    25                 // G++ Test();
    26     
    27     throw 1;  // BCC Abnormal program termination;
    28               // VC 对话框弹出来;
    29               // G++ terminate called after throwing an instance of 'int'
    30           
    31     return 0;
    32 }

        1,有了线索,main() 函数中抛出的异常也许会被一个最终的函数处理;

       

    5,异常无法被处理的情况:

        1,如果异常无法被处理,terminate() 结束函数会被自动调用;

        2,默认情况下,terminate() 调用库函数 abort() 终止程序;

           1,三款编译器在 terminate() 函数内部实现上面有点儿差异;

           2,比如打印字符串提示当前程序出来异常,弹出对话框告诉用户当前应程序要异常终止(实际还没终止);

        3,abort() 函数使得程序执行异常而立即退出;

        4,C++ 支持替换默认的 terminate() 函数实现;

           1,C++ 可以自定义结束函数,自定义最终处理异常的函数来替换预定义的 terminate();

       

    6,terminate() 函数的替换:

        1,自定义一个无返回值无参数的函数;

           1,不能抛出任何异常;

               1,最后处理异常的函数了,所以不能抛出任何异常;

           2,必须以某种方式结束当前程序;

               1,没有做到这一点儿,程序出现什么样的行为就不得而知了,当然 Windows 和 Linux 系统会将这个程序自动终止;

        2,调用 set_terminate() 设置自定义的结束函数;

           1,参数类型为 void(*)();

               1,函数指针,没有参数、没有返回值;

           2,返回值为默认的 terminate() 函数入口地址;

          

    7,自定义结束函数编程实验:

     1 #include <iostream>
     2 #include <cstdlib>
     3 #include <exception>  // C++ 标准库中与异常相关的头文件;
     4 
     5 using namespace std;
     6 
     7 void my_terminate()
     8 {
     9     cout << "void my_terminate()" << endl;
    10     exit(1);  // 结束当前的程序;可以确保所有的全局对象和静态局部对象全部都正常析构;
    11     // abort();  // “已放弃”是这个函数打印出来的,这个函数是异常终止一个程序,并且异常终止的时候不会调用任何对象的析构函数;
    12 }
    13 
    14 class Test 
    15 {
    16 public:
    17     Test() 
    18     {
    19         cout << "Test()"; 
    20         cout << endl;
    21     }
    22     
    23     ~Test() 
    24     {
    25         cout << "~Test()"; 
    26         cout << endl;
    27     }
    28 };
    29 
    30 int main()
    31 {
    32     set_terminate(my_terminate);
    33     
    34     static Test t;  
    35     
    36     throw 1;  
    37     
    38     return 0;
    39 }

        1,打印结果:

           1,exit(1) 的时候:

              Test()

              void my terminate()

              ~Test()

           2,abort() 的时候:

              Test()

              void my terminate()

              已放弃

        2,在 main() 函数中扔出的异常如果没有被处理,会被最终的一个全局结束函数处理掉;

        3,C++ 编译器之间存在差异;

       

    8,问题:

        1,如果析构函数中抛出异常会发生什么情况?

           1,前面说有可能导致资源无法释放,内存泄漏等;

           2,这里有两点:

               1,析构函数是释放资源的地方,如果抛出异常,有可能导致资源无法正确的释放;

               2,在析构函数中抛出异常有可能导致全局的结束函数 terminate() 被重复的调用,这是很可怕的,有可能让我们的系统进入一个不稳定的状态;

        2,析构函数抛出异常编程实验:

     1 #include <iostream>
     2 #include <cstdlib>
     3 #include <exception>
     4 
     5 using namespace std;
     6 
     7 void my_terminate()
     8 {
     9     cout << "void my_terminate()" << endl;
    10     // exit(1);
    11     abort();
    12 }
    13 
    14 class Test 
    15 {
    16 public:
    17     Test() 
    18     {
    19         cout << "Test()"; 
    20         cout << endl;
    21     }
    22     
    23     ~Test() 
    24     {
    25         cout << "~Test()"; 
    26         cout << endl;
    27         
    28         throw 2;
    29     }
    30 };
    31 
    32 int main()
    33 {
    34     set_terminate(my_terminate);
    35     
    36     static Test t;
    37     
    38     throw 1;
    39     
    40     return 0;
    41 }

        1,打印结果:

           1,Test()

              void my terminate()  // main() 中 throw 1 抛出异常后第一次执行 my_terminate() 函数的结果;

              ~Test()  // 调用 exit(),执行析构函数;

              void my terminate()  // 在执行析构函数的时候,再次扔出异常 throw 2,第二次执行 my_terminate() 函数;

        2,my_terminate() 函数:

           1,作为最后一个被调用的异常处理函数,任务是很重的;

           2,要负责进行应用程序级别的资源释放;

           3,第一次调用的时候,所有的资源已经被释放完了,第二次调用就类似对堆空间的内存第二次释放,造成应用程序的不稳定,因为这里 Linux 系统非常稳定,会帮我们处理好连续释放资源的问题;

           4,如果进行嵌入式开发,操作系统就不见得有这样的能力对每一个系统做这样的监控,产生的行为使未定义的;

           5,这也解释了 C++ 默认调用的是 abort() 而不是 exit(1),因为 abort() 直接的强制结束当前的应用程序,不会调用析构函数,就是拍析构函数中扔出异常;

          

    9,小结:

        1,如果异常没有被处理,最后 terminate() 结束整个程序;

        2,terminate() 是整个程序释放系统资源的最后机会;

        3,结束函数可以自定义,但不能继续抛出异常;

        4,析构函数中不能抛出异常,可能导致 terminate() 多次调用;

  • 相关阅读:
    学会分辨
    学会自重
    GIT使用笔记-fatal:multiple stage entries for merged file处理办法
    GIT-查看本地html帮助文档
    VS2013 GIT 克隆远程仓库
    GIT远程仓库地址变更
    VS2013中使用git发布解决方案master分支的时候出现错误
    C# WebService输出JSON 实现二
    WINDOWS下PhoneGap(Cordova)安装笔记
    SQLSERVER2012 Audit (审核)功能
  • 原文地址:https://www.cnblogs.com/dishengAndziyu/p/10920123.html
Copyright © 2011-2022 走看看