外传篇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()多次调用

时间: 2024-12-24 07:07:52

外传篇1 异常处理深度解析的相关文章

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

我们之前学习了异常有关的知识,那么如果在 main 函数中中抛出异常会发生什么呢?如果异常不进行处理,最后会传到哪里呢?如下 下来我们就来做个实验,代码如下 #include <iostream> using namespace std; class Test { public:     Test()     {         cout << "Test()" << endl;     }          ~Test()     {       

本篇为你深度解析 Python 异步到底是怎么实现的?

简述 PEP492 引入了对 Python 3.5 的原生协程和 async/await 句法的支持.本次提案添加了对异步生成器的支持进而来扩展 Python 的异步功能. 理论和目标 常规生成器(在 PEP 255 中引入)的实现,使得编写复杂数据变得更优雅,它们的行为类似于迭代器. 当时没有提供async for使用的异步生成器. 编写异步数据生成器变得非常复杂,因为必须定义一个实现 aiter 和 anext 的方法,才能在 async for 语句中使用它. 为了说明异步生成器的重要性,

SpringMVC 源代码深度解析&lt;context:component-scan&gt;(扫描和注册的注解Bean)

我们在SpringMVC开发项目中,有的用注解和XML配置Bean,这两种都各有自己的优势,数据源配置比较经常用XML配置,控制层依赖的service比较经常用注解等(在部署时比较不会改变的),我们经常比较常用的注解有@Component是通用标注,@Controller标注web控制器,@Service标注Servicec层的服务,@Respository标注DAO层的数据访问.SpringMVC启动时怎么被自动扫描然后解析并注册到Bean工厂中去(放到DefaultListableBeanF

Unity加载模块深度解析(网格篇)

在上一篇 加载模块深度解析(一)中,我们重点讨论了纹理资源的加载性能.这次,我们再来为你揭开其他主流资源的加载效率. 这是侑虎科技第53篇原创文章,欢迎转发分享,未经作者授权请勿转载.同时如果您有任何独到的见解或者发现也欢迎联系我们,一起探讨.(QQ群465082844) 资源加载性能测试代码 与上篇所提出的测试代码一样,我们对于其他资源的加载性能分析同样使用该测试代码.我们将每种资源均制作成一定大小的AssetBundle文件,并逐一通过以下代码在不同设备上进行加载,以期得到不同硬件设备上的资

[WebKit内核] JavaScript引擎深度解析--基础篇(一)字节码生成及语法树的构建详情分析

[WebKit内核] JavaScript引擎深度解析--基础篇(一)字节码生成及语法树的构建详情分析 标签: webkit内核JavaScriptCore 2015-03-26 23:26 2285人阅读 评论(1) 收藏 举报  分类: Webkit(34)  JavascriptCore/JIT(3)  版权声明:本文为博主原创文章,未经博主允许不得转载. 看到HorkeyChen写的文章<[WebKit] JavaScriptCore解析--基础篇(三)从脚本代码到JIT编译的代码实现>

深度解析Istio系列之Istio-proxy初始化篇

注:以下讲述的按理环境场景是基于Kubernetes环境基础上部署的Istio环境. 涉及到Envoy概念介绍请参考深度解析Istio系列之流量控制篇.本文重点针对Envoy初始化场景进行拆解. Istio-proxy(Envoy)作为Istio数据平面的重要组件,基于sidecar方式与业务应用混合部署到同一pod,为应用提供代理服务.Pilot作为控制平面组件,基于元数据的抽象层,屏蔽底层具体容器环境(Kubernetes或者docker),同时为Envoy的策略执行提供有效的数据支撑.那么

AndroidService 深度解析(2)

AndroidService 深度解析(2) 上一篇文章我们对Service的生命周期进行了测试及总结.这篇文章我们介绍下绑定运行的Service的实现. 绑定运行的Service可能是仅为本应用提供服务,称为本地Service:也可能为其他应用提供跨进程服务,即远程Service.下面分别进行介绍: 本地Service 如果Service只服务于本应用,那么我们只需要继承Binder类,定义我们需要实现的方法即可,当发起绑定连接时,Service将会在onBind方法中返回这个继承类的对象,使

Deep Learning模型之:CNN卷积神经网络(一)深度解析CNN

http://m.blog.csdn.net/blog/wu010555688/24487301 本文整理了网上几位大牛的博客,详细地讲解了CNN的基础结构与核心思想,欢迎交流. [1]Deep learning简介 [2]Deep Learning训练过程 [3]Deep Learning模型之:CNN卷积神经网络推导和实现 [4]Deep Learning模型之:CNN的反向求导及练习 [5]Deep Learning模型之:CNN卷积神经网络(一)深度解析CNN [6]Deep Learn

Android Service 深度解析(1)

Android Service 深度解析(1) 这段时间我重新对Android基础进行了学习,还是先从官方文档开始,做了关于Service的文档翻译,熟悉了关于Service的知识点.但是在用的时候还是有很多需要注意的地方,需要把这些知识点联系起来,因此有了这篇文章.我将主要从以下几个方面对Service类进行深度解析: 1. Service的生命周期(看起来简单,实际上很复杂的): 2. 绑定运行Service(Bound Service)的多种形式实现及其使用: 主要包括本地Service继