zoukankan      html  css  js  c++  java
  • 异常处理深度解析

    问题:
    如果在main函数中抛出异常会发生什么?

    #include <iostream>
    
    using namespace std;
    
    class Test
    {
    public:
        Test()
        {
            cout << "Test()" << endl;
        }
    
        ~Test()
        {
            cout << "~Test()" << endl;
        }
    };
    
    
    int main()
    {
        static Test t;
    
        throw 1;
    
        return 0;
    }

     不同的编译器打印结果是不同的,但是根据我们编写的程序,不管哪款编译器Test()是肯定会被打印的。差异就在下面打印的东西。使用的该款编译器,当抛出异常时terminate函数被调用了。

    如果异常无法被处理,terminate()结束函数会被自动调用
    默认情况下,terminate()调用库函数abort()终止程序
    abort()函数使得程序执行异常而立即退出
    C++支持替换默认的terminate()函数实现

    #include <iostream>
    #include <cstdlib>
    #include <exception>
    
    using namespace std;
    
    void my_terminate()
    {
        cout << "void my_terminate()" << endl;
        exit(1);
    }
    
    class Test
    {
    public:
        Test()
        {
            cout << "Test()" << endl;
        }
    
        ~Test()
        {
            cout << "~Test()" << endl;
        }
    };
    
    
    int main()
    {
        set_terminate(my_terminate);
        static Test t;
    
        throw 1;
    
        return 0;
    }

    exit函数会确保所有的全局对象和静态局部对象全部被正常的析构。如果不调用exit,而是调用abort,又会发生什么?

    不会调用析构函数,abort是异常终止一个程序,当它异常终止一个程序时,不会调用任何对象的析构函数。

    通过本实验,可以得出下面两条结论:

    1.在main函数中所扔出的异常如果没有被处理,最终将被一个全局函数处理掉。
    2.c++编译器之间存在差异

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

    #include <iostream>
    #include <cstdlib>
    #include <exception>
    
    using namespace std;
    
    void my_terminate()
    {
        cout << "void my_terminate()" << endl;
        exit(1);
    }
    
    class Test
    {
    public:
        Test()
        {
            cout << "Test()" << endl;
        }
    
        ~Test()
        {
            cout << "~Test()" << endl;
            throw 2;
        }
    };
    
    
    int main()
    {
        set_terminate(my_terminate);
        static Test t;
    
        throw 1;
    
        return 0;
    }

     你会发现全局函数my_terminate被重复的调用。

    已经调用了析构函数,又重复调用析构函数。类似于一个指针指向了堆空间中的一片内存,delete一次就把它释放掉了,如果delete两次就会有问题,造成整个应用程序的不稳定。

    当把exit函数换成abort时,又会怎样呢?前面已经说过abort函数是不会调用析构函数的

    从而就解释了,在terminate函数中,C++默认调用的是abort,而不是exit了。因为abort函数强制的结束当前的应用程序了,它不会去调用析构函数,就是害怕析构函数中又抛出异常

    现在可以回答上面提出的问题了,可以在析构函数中扔出异常,但一定不要这样做。这样做会导致很多问题。

    原则:在析构函数中一定不要抛出异常,原因如下:

    析构函数是用来释放资源的地方,如果抛出异常,有可能导致资源得不到正确的释放
    在析构函数里面抛出异常有可能导致全局的结束函数terminate被重复的调用,这是极其可怕的事情,有可能让系统进入极其不稳定的状态。

    小结:

    terminate函数 可以在调用abort函数之前,打印一些字符串,弹出一个对话框出来。

  • 相关阅读:
    [.Net MVC] 使用 log4net 日志框架
    322作业
    uva 12171 sculpture (超级好题)——yhx
    NOIP2007 T2纪念品分组 解题报告-S.B.S.
    NOIP2007 T1奖学金 解题报告-S.B.S.
    NOIP2012普及组 (四年后的)解题报告 -SilverN
    calc 多项式计算 (STL版和非STL版) -SilverN
    uva 10562 undraw the trees(烂题) ——yhx
    uva 10129 play on words——yhx
    uva 10305 ordering tasks(超级烂题)——yhx
  • 原文地址:https://www.cnblogs.com/-glb/p/12301005.html
Copyright © 2011-2022 走看看