C++析构函数调用异常问题研究】的更多相关文章

最近又遇到一个奇葩问题,程序在自己的开发机器和某些机器上运行完好,但是在测试人员的几台机器上运行就直接推出了.开始以为是出现了野指针,因为delete野指针时程序会直接退出.代码翻来覆去过来即便确认没有野指针后问题就陷入了死循环.经过多次调试我发现在我的机器上虽然不崩溃,但是delete对象指针的时候不会走对应的析构函数,这问题就奇怪了.后来终于被我找到了原因.原来在头文件中声明成员变量指针时为了尽量少的包含头文件而使用的前向声明,而在实现文件中又没有包含真正声明该类型的头文件.一般情况下这种使…
先看一个例子: #include <iostream> using namespace std; class A{ public: A() { show(); } virtual void show(){ cout<<"in A"<<endl; } virtual ~A(){ show(); } }; class B:public A{ public: B() { show(); } void show(){ cout<<"in…
1.继承构造函数调用顺序以及销毁的过程 先调用父类的构造函数,在调用子类的构造函数,析构函数调用相反.…
1.深/浅拷贝 编译器为我们提供的合成拷贝构造函数以及合成的拷贝赋值运算符都是浅拷贝.浅拷贝只是做简单的复制,如果在类的构造函数中new出了内存,浅拷贝只会简单的复制一份指向该内存的指针,而不会再开辟内存,这就会使得程序运行出现内存错误,如此,当对象析构的时候,会delete多次同一块内存区域,发生错误.这也就是为什么,必要的时候需要我们自己编写拷贝构造函数和重载赋值运算符,让它变成深拷贝,深拷贝即在copy指针的时候不是简单做值copy,而是还要开辟内存. 2.构造函数析构函数调用顺序练习题…
版权声明:本文由谢代斌原创文章,转载请注明出处: 文章原文链接:https://www.qcloud.com/community/article/108 来源:腾云阁 https://www.qcloud.com/community 研究测试TCP断开和异常的各种情况,以便于分析网络应用(比如tconnd)断网的原因和场景,帮组分析和定位连接异常掉线的问题,并提供给TCP相关的开发测试人员作为参考. 各个游戏接入都存在一定的掉线问题,而且有的游戏项目的掉线比例还比较高,现在互娱自研游戏的网络接入…
一:背景 1.讲故事 最近遇到一位朋友的程序崩溃,发现崩溃点在富编辑器 msftedit 上,这个不是重点,重点在于发现他已经开启了 页堆 ,看样子是做了最后的挣扎. 0:000> !analyze -v EXCEPTION_RECORD: (.exr -1) ExceptionAddress: 82779a9e (msftedit!CCallMgrCenter::SendAllNotifications+0x00000123) ExceptionCode: c0000005 (Access v…
#include <iostream> using namespace std; class A { public: A () { cout<<"A 构造 "<<endl; } virtual ~A() // 定义虚析构函数 导致原来析构顺序发生变化 { cout<<"A 析构 "<<endl; } }; class B : public A { public: B () { cout<<&qu…
构造函数和析构函数中的虚函数 在执行基类构造函数时,对象的派生类部分是未初始化的.实际上,此时对象还不是一个派生类对象. 为 了适应这种不完整,编译器将对象的类型视为在构造或析构期间发生了变化.在基类构造函数或析构函数中,将派生类对象当作基类类型对象对待.   如果在构造函数或析构函数中调用虚函数,则运行的是为构造函数或析构函数自身类型定义的版本.   class Base { public: Base() { Fuction(); } virtual void Fuction() { cout…
/*当建立一个对象时,首先调用基类的构造函数,然后调用下一个派生类的构造函数,依次类推,直至到达派生类次数最多的派生次数最多的类的构造函数为止.简而言之,对象是由“底层向上”开始构造的.因为,构造函数一开始构造时,总是要调用它的基类的构造函数,然后才开始执行其构造函数体,调用直接基类构造函数时,如果无专门说明,就调用直接基类的默认构造函数.在对象析构时,其顺序正好相反.下面的这个程序说明这个问题*///-----------------------------------------------…
今天看书忽然对这个地方有点模糊,尤其是析构函数在调用默认的析构函数和用户自己覆写的析构函数的时候有点意识模糊呢.写段代码总结下 #include <iostream> using namespace std; class Box { private: double length; public: Box(double lv=1.0):length(lv)//构造函数都没有返回值 { cout << "constructor called" << en…
单个对象创建时,构造函数的调用顺序 1.首先判断该对象的类是否拥有父类,若有则先调用父类的构造函数 2.判断该对象的成员是否是其它类的成员,若是则调用成员变量的构造函数(调用顺序和声明顺序相同) 3.最后调用对象本身类的构造函数 单个对象被注销后,调用的析构函数与对应构造函数的调用顺序相反 参考下面示例,创建两个类Member,Test,然后Tesrt成员包含了Member类的成员: #include <stdio.h> class Member { const char* ms; publi…
by zhangxinxu from http://www.zhangxinxu.com/wordpress/?p=5569 一.Safari是新时代的IE6 在2年前介绍currentColor变量的时候就提过Safari的问题,就是伪元素hover时候的currentColor不渲染, 像这种IE浏览器都可以正常渲染的CSS,Safari居然出现各种匪夷所思的问题,对的,是各种,而且全都是与渲染相关的,这也难怪为什么Safari浏览器被称为“新时代的IE6”了! 补充于2016-08-09S…
示例函数 注:输出并不一定从main函数开始,如全局对象的初始化在main函数前执行,如构造函数中存在输出,则从构造函数的输出开始 此处6被类型转换构造函数的存在转换为临时对象赋值,而在这个过程结束后临时对象消亡则调用析构函数 注2:局部变量生存期是碰到函数开始到最内存函数右边花括号 注3:静态局部变量则会留存到整个程序结束 注4:构造函数并非分配变量的存储空间,而是负责初始化,而析构函数也不负责收回变量的存储空间 注5:new的对象如果不用delete删除则不会消亡,不会触发析构函数,即使整个…
前言 本文是异常内容的集大成者,力求全面,深入的异常知识研究与分析.本文由金丝燕网独家撰写,参考众多网上资源,经过内容辨别取舍,文字格式校验等步骤编辑而成,以飨读者.对于本文的内容,建议小白需要多多思考力求掌握,对于老手只需意会温故知新.对于本文的内容,属于基础知识研究范畴,切勿以为读完此文就能将异常知识掌握到家.切记:操千曲而后晓声,观千剑而后识器,所以我觉得没有大量的源码阅读经验,你很难知道什么时候需要自定义异常,什么时候需要抛出异常. 异常机制概述 异常机制是指当程序出现错误后,程序如何处…
析构函数绝对不要吐出异常.如果一个被析构函数调用的函数可能抛出异常,析构函数应该捕捉任何异常,然后吞下它们(不传播)或结束程序. 如果客户需要对某个操作函数运行期间抛出的异常作出反应,那么class应该提供一个普通函数(而非在析构函数中)执行该操作.…
条款05:了解C++默默编写并调用哪些函数 默认构造函数.拷贝构造函数.拷贝赋值函数.析构函数构成了一个类的脊梁,只有良好的处理这些函数的定义才能保证类的设计良好性. 当我们没有人为的定义上面的几个函数时,编译器会给我们构造默认的. 当成员变量里有const对象或引用类型时,编译器会不能合成默认的拷贝赋值函数:当一个基类把它的拷贝赋值函数定义为private时,它的派生类也不无生成默认的拷贝赋值函数,因为它无法完成基类成份的赋值. 条款06:若不想使用编译器自动生成的函数,就该明确拒绝 将拷贝构…
这章非常容易理解:因为C++并不禁止析构函数吐出异常,只是不鼓励这样做而已. 一.原因 假设我们有10个装着鸡蛋的容器,而且现在我们还想着把它在析构函数打烂. class Egg { public : ... ~Egg() { // 这里可能出错,导致蛋打不烂 } }; void foo() { vector<Egg> v // 假设v中间有10个Egg .... } // v在这里被自动销毁 如果我们在销毁10个鸡蛋的过程中,在析构第一个鸡蛋的时候,有个异常被抛出,按照销毁机制,后续的9个鸡…
条款05:了解C++默默编写并调用哪些函数 编译器默认声明一个default构造函数.一个copy构造函数.一个copy assignment操作符和一个析构函数.这些函数都是public且inline. class Empty { public: Empty() {...} Empty(const Empty& rhs) {...} ~Empty() {...} Empty& operator=(const Empty& rhs) {...} }; 如果你打算在一个内含refer…
条款8 别让异常逃离析构函数 记住: ★析构函数绝对不要吐出异常.若一个被析构函数调用的函数可能抛出异常,析构函数应该捕捉任何异常,然后吞下它们(不传播)或结束程序. ★若客户需对某个操作函数运行期间抛出的异常做出反应,那么class应提供一个普通函数(而非在析构函数)执行该操作. ------------------------------------------------------------------------------------------------------------…
(整理自Effctive C++,转载请注明.整理者:华科小涛@http://www.cnblogs.com/hust-ghtao/) C++并不禁止析构函数吐出异常,但它不鼓励你这样做.考虑如下代码: 1: class Widget{ 2: public: 3: ... 4: ~Widget() {...} //假设这个可能吐出一个异常 5: }; 6:  7: void doSomething() 8: { 9: vector<Widget> v ; //v在这里被自动销毁 10: ...…
1.为什么c++不喜欢析构函数抛出异常 C++并没有禁止析构函数出现异常,但是它肯定不鼓励这么做.这是有原因的,考虑下面的代码: class Widget { public: ... ~Widget() { ... } // assume this might emit an exception }; void doSomething() { std::vector<Widget> v; ... } // v is automatically destroyed here 当vector V被…
条款五:了解C++默认编写并调用那些函数 是否存在空的类? 假设定义类为class Empty{}:当C++编译器处理过后会变成如下的形式: class Empty{ Empty(){} ~Empty(){} Empty& operator=(const Empty& rhs){.....} Empty(const Empty& rhs){.....} } 可以分别称为构造函数,析构函数,赋值构造函数,复制构造函数!惟有当这些函数被需要(被调用),它们才会被编译器创建出来.下面代码…
一 构造析构常识: 1,c++ 处理类,若没有声明,则编译器默认声明构造,拷贝赋值,拷贝构造,析构函数.所有这些函数都是public且inline的. 2,编译器产出的析构函数是非虚函数.(non-virtual). 3,拷贝构造和拷贝赋值函数作用就是拷贝非静态成员变量到目标对象处. 4,如果打算在内部含有引用成员的类内支持赋值操作,必须自己定义拷贝赋值函数.operator = 5,若不想使用默认函数,最好在编程时候明确拒绝.............................. 因为有时…
1.别让异常逃离析构函数的原因 <Effective C++>第三版中条款08建议不要在析构函数中抛出异常,原因是C++异常机制不能同时处理两个或两个以上的异常.多个异常同时存在的情况下,程序若不结束,会导致不明确行为.如下代码: class Widget{ public: ~Widget(){...} //假设这个可能吐出一个异常 }; void dosomething(){ vector<Widget> v; } //v在这里被自动销毁 函数dosomething运行结束后,最…
条款05 : 了解C++默默编写并调用哪些函数 编译器可以暗自为class创建default构造函数.copy构造函数.copy assignment操作符,以及析构函数. 1. default构造函数和析构函数:主要是给编译器一个地方用来放置“藏身幕后”的代码,像是调用base classes和non-static成员变量的构造和析构函数:当我们显式声明了一个构造函数,编译器于是不再为我们的类创建default构造函数. 2. 如果你打算在一个“内含reference成员”的class内支持赋…
参考:http://www.cnblogs.com/ronny/p/3740926.html 条款05:了解C++默默编写并调用哪些函数 如果自定义一个空类的话,会自动生成默认构造函数.拷贝构造函数.拷贝赋值函数.析构函数(再次感觉原文翻译的实在是太啰嗦了!). 当成员变量里有const对象或引用类型时,编译器会不能合成默认的拷贝赋值函数:当一个基类把它的拷贝赋值函数定义为private时,它的派生类 也不能生成默认的拷贝赋值函数,因为它无法完成基类成份的赋值. 条款06:若不想使用编译器自动生…
章节回顾: <Effective C++>第1章 让自己习惯C++-读书笔记 <Effective C++>第2章 构造/析构/赋值运算(1)-读书笔记 <Effective C++>第2章 构造/析构/赋值运算(2)-读书笔记 <Effective C++>第3章 资源管理(1)-读书笔记 <Effective C++>第3章 资源管理(2)-读书笔记 <Effective C++>第4章 设计与声明(1)-读书笔记 <Eff…
c++11开始支持多线程编程,相关的类和函数封装在标准库头文件<thread>中,而c++多线程编程很重要的一点就是当用户创建一个std::thread对象,关联了可调用对象后,需要在该thread对象销毁前调用join()或detach().其中join()函数用于结合线程,确保在创建该thread对象的函数退出前,该线程执行完毕;而detach()函数则表示分离线程,即让线程在后台运行,线程的所有权和控制权交给c++运行时库.若thread对象销毁前没有调用join()或detach(),…
考虑如下代码: class Widget{ public: ... ~Widget(){...}//假设这个可能吐出一个异常 }; void doSomething() { std::vector<Widget>v; }//v在这里被销毁 当vector v被销毁,它有责任销毁其内含的所有Widgets.假设v内含十个Widgets,而在析构第一个元素期间,有个异常被抛出.其他九个Widgets还是应该被销毁,因此v应该调用它们各个析构函数.假设在调用期间,第二个Widget析构函数又抛出异常…