189 8069 5689

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

        我们之前学习了异常有关的知识,那么如果在 main 函数中中抛出异常会发生什么呢?如果异常不进行处理,最后会传到哪里呢?如下

创新互联服务项目包括潘集网站建设、潘集网站制作、潘集网页制作以及潘集网络营销策划等。多年来,我们专注于互联网行业,利用自身积累的技术优势、行业经验、深度合作伙伴关系等,向广大中小型企业、政府机构等提供互联网行业的解决方案,潘集网站推广取得了明显的社会效益与经济效益。目前,我们服务的客户以成都为中心已经辐射到潘集省份的部分城市,未来相信会继续扩大服务区域并继续获得客户的支持与信任!

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

        下来我们就来做个实验,代码如下

#include 

using namespace std;

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

int main()
{
    static Test t;
    
    throw 1;
    
    return 0;
}

        我们先来看看 g++ 编译器是怎样处理的

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

        我们看到在打印了构造函数的语句之后,下面还输出两句话,那么我们并没有在程序中定义这样的输出啊,这个到底是谁打印出来的呢?我们来看看 BCC 编译器

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

        在 BCC 编译器中输出了下面的一句话,也并不是我们定义的。我们再来看看 vs2010 编译器

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

        我们看到在 vs2010 编译器中弹出了一个对话框,我们并没有编写相关的代码。我们来看看编译器在背后究竟做了哪些事,如果异常无法被处理,terminate() 结束函数会被自动调用。默认情况下,terminate() 调用库函数 abort() 终止程序,abort() 函数使得程序执行异常而立即退出,C++ 支持替换默认的 terminate() 函数实现。

        terminate() 函数的替换:a> 它是自定义一个无返回值无参数的函数,不能抛出任何异常,必须以某种方式结束当前程序;b> 调用 set_terminate() 设置自定义的结束函数,参数类型为 void(*)(),返回值为默认的 terminate() 函数入口地址。

        下来我们来自定义 terminate() 函数。

#include 
#include 
#include 

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

        我们再来看看编译结果,先在 g++ 编译器下

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

        我们看到程序正常运行结束了。我们来分析下,我们在 main 函数中调用 set_terminate() 设置结束函数 my_terminate()。在 main 函数中抛出了一个异常,被结束函数 my_terminate() 捕获到了,然后执行它里面的打印语句,进而执行到 exit(1) 正常退出。所以在最后退出的时候会去执行析构函数。我们再来看看 BCC 编译器呢

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

        我们看到和 g++ 编译器中的行为是一样的,再来看看 vs2010 编译器看看

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

        那么如果在析构函数中抛出异常会发生什么情况呢?我们来试试,在上面的程序中的析构函数抛出一个异常,看看编译结果

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

        我们看到最后又去调用内置的 Aborted 函数了。再来看看 BCC 编译器呢

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

        同样也是这样的情况,看看 vs2010 编译器

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

        我们来分析下,它先是在 main 函数中抛出异常,然后执行到 my_terminate() 函数中,进而退出(清理一切资源等),在退出的时候又去执行析构函数,又再次抛出异常,等于又要再次进行资源的释放,造成二次释放了。类似于在操作指针时,二次释放,所带来的后果是无法确定的。因此它最后会去调用库函数中的 abort() 函数。因此,我们在 main 函数中尽量不要抛出异常。通过对异常的深度学习,总结如下:1、如果异常没有被处理,最后 terminate() 结束整个程序;2、terminate() 是整个程序释放系统资源的最后机会;3、结束函数可以自定义,但不能继续抛出异常;4、析构函数中不能抛出异常,可能导致 terminate() 多次调用。

        欢迎大家一起来学习 C++ 语言,可以加我QQ:243343083。


分享名称:异常处理深度解析(五十八)
文章地址:http://cdxtjz.cn/article/jjehss.html

其他资讯