抛出异常与栈展开(stack unwinding)
抛出异常时,将暂停当前函数的执行,开始查找匹配的catch子句。首先检查throw本身是否在try块内部,如果是,检查与该try相关的catch子句,看是否可以处理该异常。如果不能处理,就退出当前函数,并且释放当前函数的内存并销毁局部对象,继续到上层的调用函数中查找,直到找到一个可以处理该异常的catch。这个过程称为栈展开(stack unwinding)。当处理该异常的catch结束之后,紧接着该catch之后的点继续执行。

1. 为局部对象调用析构函数
如上所述,在栈展开的过程中,会释放局部对象所占用的内存并运行类类型局部对象的析构函数。但需要注意的是,如果一个块通过new动态分配内存,并且在释放该资源之前发生异常,该块因异常而退出,那么在栈展开期间不会释放该资源,编译器不会删除该指针,这样就会造成内存泄露。

2. 析构函数应该从不抛出异常
在为某个异常进行栈展开的时候,析构函数如果又抛出自己的未经处理的另一个异常,将会导致调用标准库terminate函数。通常terminate函数将调用abort函数,导致程序的非正常退出。所以析构函数应该从不抛出异常。

3. 异常与构造函数
如果在构造函数对象时发生异常,此时该对象可能只是被部分构造,要保证能够适当的撤销这些已构造的成员。

4. 未捕获的异常将会终止程序
不能不处理异常。如果找不到匹配的catch,程序就会调用库函数terminate。

因此,在有可能发生异常的函数中,可以利用“智能指针”auto_ptr来防止内存泄露。参考如下程序。

#include <iostream>
#include <memory>
using namespace std;class A{int num;
public:A(int i):num(i){cout<<"this is A's constructor, num="<<num<<endl;}~A(){cout<<"this is A's destructor, num="<<num<<endl;}void show(){cout<<num<<endl;}
};void autoptrtest1(){A* pa=new A(1);throw 1;delete pa;
}void autoptrtest2(){auto_ptr<A> pa(new A(2));pa->show();throw 2;
}int main(){try{autoptrtest1();}   catch(int){cout<<"there is no destructor invoked"<<endl;}cout<<endl;try{autoptrtest2();}catch(int){cout<<"A's destructor does be invoked"<<endl;}
}

程序的输出结果:
this is A’s constructor, num=1
there is no destructor invoked

this is A’s constructor, num=2
2
this is A’s destructor, num=2
A’s destructor does be invoked

在解读上面的这段程序的时候,要注意以下几点。

(1)在函数autoptrtest1()中,由于异常的发生,导致delete pa;无法执行,从而导致内存泄露。

(2)auto_ptr实际上是一个类模板,在名称空间std中定义。要使用该类模板,必须包含头文件memory。auto_ptr的构造函数可以接受任何类型的指针,实际上是利用指针类型将该类模板实例化,并将传入的指针保存在auto_ptr< T>对象中。

(3)在栈展开的过程中,auto_ptr< T>对象会被释放,从而导致auto_ptr< T>对象的析构函数被调用。在该析构函数中,将使用delete运算符将保存在该对象内的指针所指向的动态对象被销毁。这样,就不会发生内存泄露了。

(4)由于已经对*和->操作符进行了重载,所以可以像使用普通的指针变量那样使用auto_ptr< T>对象,如上面程序中的pa->show()。这样可以保留使用指针的编程习惯,方便程序猿编写和维护。

转自下面两篇博客:
http://www.cnblogs.com/zhuyf87/archive/2012/12/23/2829725.html
http://blog.csdn.net/K346K346/article/details/50157297
//————————-分界线——————————-
在这里顺便也把异常关于在析构函数内的内容写一下学习笔记。
内容是more effective 条款11:禁止exceptions流出destructors之外。

class Session{
pubilc:Session();~Session();...
private:static void logCreation(Session *obj);static void logDestruction(Session *obj);
}
Session::~Session(){logDestruction(this);
}

如果在~Session调用时logDestruction抛出一个exception,这个exception不会被Session destructor捕捉,然后就会发生栈展开,传播到destructor的调用端,但是万一这个destructor本身是因为其他某个exception而被调用的,terminate函数便会被自动调用,于是程序终止。
解法:
Session ::~Session(){
try{
logDestruction(this);
}
catch(…){}
}
这个语句块阻止了logDestruction抛出的exception传出Session destructor之外。如果一个Session object因为栈展开而被销毁,terminate并不会被调用。
好处:
1.避免terminate函数在exception传播过程的栈展开机制中被调用。
2.可以协助确保destructor完成其应该完成的所有事情。

栈展开(stack unwinding)在destructors中的exceptions相关推荐

  1. 栈展开(stack unwinding)

    栈展开(stack unwinding)的定义 抛出异常时,将暂停当前函数的执行,开始查找匹配的 catch 子句.首先检查 throw 本身是否在 try 块内部,如果是,检查与该 try 相关的 ...

  2. c++抛出异常与栈展开(stack unwinding)

    抛出异常时,将暂停当前函数的执行,开始查找匹配的catch子句.首先检查throw本身是否在try块内部,如果是,检查与该try相关的catch子句,看是否可以处理该异常.如果不能处理,就退出当前函数 ...

  3. noexcept与栈展开(stack unwinding)

    noexcept说明 在C++11之后,表示函数不会抛出异常的动态异常声明throw()被新的noexcept异常声明所取代. 该关键字告诉编译器,函数中不会发生异常,这有利于编译器对程序做更多的优化 ...

  4. 抛出异常与栈展开(stack unwinding)

    抛出异常时,将暂停当前函数的执行,开始查找匹配的catch子句.首先检查throw本身是否在try块内部,如果是,检查与该try相关的catch子句,看是否可以处理该异常.如果不能处理,就退出当前函数 ...

  5. java中stack heap_java虚拟机中的堆(heap)、栈(stack)、方法区(method area)

    1.堆区 存储的全部是对象,每个对象都包含一个与之对应的class的信息.(class的目的是得到操作指令) jvm只有一个heap区,被所有线程共享,不存放基本类型和对象引用,只存放对象本身 堆的优 ...

  6. C++ 栈展开如何防止内存泄露

    在栈展开(stack unwinding)是指,如果在一个函数内部抛出异常,而此异常并未在该函数内部被捕捉,就将导致该函数的运行在抛出异常处结束,所有已经分配在栈上的局部变量都要被释放.如果被释放的变 ...

  7. C++中的stack类、QT中的QStack类

    C++中的stack 实现一种先进后出的数据结构,是一个模板类. 头文件 #include<stack> 用法(以int型为例): stack <int> s; //定义一个i ...

  8. 堆(heap)与栈(stack)的区别(一)

    堆区(heap):一般由程序员分配和释放,若程序员不释放,程序结束时可能由操作系统回收,但它与数据结构中的堆不是一回事,分配方式类似于链表. 栈(stack):由编译器自动分配和释放,存函数的参数值, ...

  9. java中的stack类和C++中的stack类的区别

    文章目录 1 java中的stack类和C++中的stack类的区别 1.1 java中的stack类 1.2 C++中的stack类 1.3 分析 不经意间想到了这个问题,存到栈中的是对象的引用,还 ...

最新文章

  1. 自学Java-运算符
  2. 【网址收藏】win10 VirtualBox安装CentOS 7教程
  3. 【重构】微信小程序倒计时组件
  4. 桌面图标摆放图案_用图标制作醒目的图案
  5. 请求接受json tp5_关于jq jsonp跨域请求错误处理bug
  6. python gui界面实例_Python界面(GUI)编程PyQt5工具栏和菜单
  7. VSCode配置ESLint
  8. 5月购机指南!新机流畅度排行榜:第一名实至名归
  9. java ajax异步验证,【求助】真的不会做了。。关于AJAX异步验证的问题。。
  10. Atlas 调用web service
  11. Caffe学习3:Layer
  12. android源码 分享1
  13. word2016 插入书签域
  14. 关于环信客服的集成与使用
  15. 如何在本地运行jsp文件
  16. POJ 2248【加法链】
  17. 点到线段的最短距离——矢量法
  18. MTU TTL RTT
  19. OCX控件全屏、恢复
  20. JVM内存区域和垃圾收集器

热门文章

  1. 前端面试题(背题中)
  2. 怎么把二维码解码成链接地址?
  3. 解决phpstorm运行很卡问题
  4. HTML 中几种常见长度单位介绍
  5. 推荐大家......必看的几部超级鬼片
  6. VCN 在windows和linux之间 复制粘贴
  7. 南卫理公会大学计算机科学,南卫理公会大学计算机科学研究生语言及申请要求-费用-课程设置...
  8. 创业起步的十大准备步骤
  9. Excel - 选择性粘贴和单元格引用规则
  10. 英语caement水泥