外传篇1 异常处理深度解析

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了外传篇1 异常处理深度解析相关的知识,希望对你有一定的参考价值。

1. 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;
}

/*输出结果:
1、g++编译
Test()
terminate called after throwing an instance of ‘int‘

This application has requested the Runtime to terminate it in an unusual way.
Please contact the application‘s support team for more information.
2. VC++编译
//然后弹出test.exe己停止工作的对话框
*/

2. 异常的最终处理

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

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

(3)abort()函数使得程序执行异常而立即退出。而不会像exit会先进行一些清理工作(如调用全局对象或静态局部对象的析构函数),再退出进程。

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

3. 自定义结束函数(terminate)

(1)自定义一个无返回值无参数的函数

  ①不能抛出任何异常

  ②必须以某种方式结束当前程序(如exit或abort

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

  ①参数类型为void(*)()

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

【编程实验】自定义结束函数

#include <iostream>

using namespace std;

//自定义结束函数
void my_terminate()
{
    cout << "void my_terminate()" << endl;
    exit(1); //调用exit会进行一些清理工作(如调用全局对象
             //或静态局部变量的析构函数来进行清理)
}

class Test
{
public:
    Test(){
        cout << "Test()" << endl;
    }
    ~Test(){
        cout << "~Test()" << endl;
    }
};

int main()
{
    set_terminate(my_terminate); //设置自定义的结束函数
    
    static Test t;  //如果是局部变量,异常发生时析构函数不会被调用
                    //因为,当异常发生后,会先执行my_terminate()结
                    //束函数,而该函数内调用的exit函数会清理全局变量
    throw 1;
    
    return 0;
}

/*输出结果:
Test()
void my_terminate()
~Test()
*/

4. 析构函数中抛异常

(1)可能造成terminate函数被重复调用

(2)由terminate的重复调用,可能造成资源重复释放,从而造成系统的不稳定。

【编程实验】析构函数中抛异常

#include <iostream>

using namespace std;

//自定义结束函数
void my_terminate()
{
    cout << "void my_terminate()" << endl;
    
    exit(1); //调用exit会进行一些清理工作
    //abort(); //abort直接退出程序,而不会进行清理操作
}

class Test
{
public:
    Test(){
        cout << "Test()" << endl;
    }
    ~Test(){
        cout << "~Test()" << endl;
        
        throw 2; //在析构函数中抛异常
    }
};

int main()
{
    set_terminate(my_terminate); //设置自定义的结束函数
    
    static Test t; 
    
    throw 1;   //1、由于main没有处理这异常,会被传递到my_terminate去处理
               //所以第1次调用my_terminate函数。
               //2、又因为my_terminate中调用了exit函数,而exit会进行一些
               //清理工作。如调用t对象的析构函数,但析构中也抛出一个异常
               //这将导致my_terminate被再次调用。这种重复调用terminate可
               //能造成资源的重复释放,从而造成系统的不稳定。
    
    return 0;
}

/*输出结果:
Test()
void my_terminate()
~Test()
void my_terminate() //析构函数中抛异常,将导致my_terminate被重复调用
*/

5. 小结

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

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

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

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

以上是关于外传篇1 异常处理深度解析的主要内容,如果未能解决你的问题,请参考以下文章

外传篇2 函数的异常规格说明

深度解析Java线程池的异常处理机制

深度解析Java线程池的异常处理机制 #3

异常处理深度解析(五十八)

Java笔记八,深度解析Java线程池的异常处理机制

异常处理深度解析