C++析构函数调用异常问题研究
最近又遇到一个奇葩问题,程序在自己的开发机器和某些机器上运行完好,但是在测试人员的几台机器上运行就直接推出了。开始以为是出现了野指针,因为delete野指针时程序会直接退出。代码翻来覆去过来即便确认没有野指针后问题就陷入了死循环。经过多次调试我发现在我的机器上虽然不崩溃,但是delete对象指针的时候不会走对应的析构函数,这问题就奇怪了。后来终于被我找到了原因。原来在头文件中声明成员变量指针时为了尽量少的包含头文件而使用的前向声明,而在实现文件中又没有包含真正声明该类型的头文件。一般情况下这种使用方式编译器会报错,但是当把指针放在容器中时编译器就不能侦测到错误了。说起来问题比较绕下面用代码写了个例子:
father.h
#ifndef FATHER_H_
#define FATHER_H_ struct FatherCalss
{
public:
virtual double Speak() = ;
virtual ~FatherCalss(); }; struct SonCalss:public FatherCalss
{
public: virtual ~SonCalss(); }; class GrandsonClass:public SonCalss
{
public:
virtual double Speak(); virtual ~GrandsonClass();
}; #endif//FATHER_H_
father.cpp
#include "stdafx.h"
#include "Father.h"
#include <Windows.h> FatherCalss::~FatherCalss()
{
MessageBox(NULL, _T("FatherCalss"), _T("~FatherCalss"), MB_OK);
} SonCalss::~SonCalss()
{
MessageBox(NULL, _T("SonCalss"), _T("~SonCalss"), MB_OK);
} GrandsonClass::~GrandsonClass()
{
MessageBox(NULL, _T("GrandsonClass"), _T("~GrandsonClass"), MB_OK);
} double GrandsonClass::Speak()
{
MessageBox(NULL, _T("Speak"), _T("~GrandsonClass"), MB_OK);
return 0.0;
}
first.h
#ifndef FIRST_H__
#define FIRST_H__
#include <vector> struct FatherCalss; class First
{
public:
void CreateObject();
~First(); std::vector<FatherCalss*> m_VecpFather;
}; #endif // First_h__
first.cpp
#include "First.h"
#include "Father.h" void First::CreateObject()
{
FatherCalss* pFth = new GrandsonClass;
pFth->Speak();
m_VecpFather.push_back(new GrandsonClass);
} First::~First()
{
for(std::vector<FatherCalss*>::iterator it = m_VecpFather.begin(); it != m_VecpFather.end(); ++it)
{
delete *it;
}
}
调用代码:
First* pFirst = new First; pFirst->CreateObject(); for(std::vector<FatherCalss*>::iterator it= pFirst->m_VecpFather.begin(); it != pFirst->m_VecpFather.end(); ++it)
{
delete *it;
}
pFirst->m_VecpFather.clear(); delete pFirst;
如上如果 m_VecpFather 不是容器而是 FatherCalss* 则编译器会报错。
运行程序后会发现对象的析构函数根本就没有被执行,这样的行为存在一定的不确定性,程序如果不报错的换实际上会产生内存泄漏。
C++析构函数调用异常问题研究的更多相关文章
- C++构造函数和析构函数调用虚函数时都不会使用动态联编
先看一个例子: #include <iostream> using namespace std; class A{ public: A() { show(); } virtual void ...
- C++单继承的构造函数和析构函数调用的顺序
1.继承构造函数调用顺序以及销毁的过程 先调用父类的构造函数,在调用子类的构造函数,析构函数调用相反.
- c++深/浅拷贝 && 构造函数析构函数调用顺序练习题
1.深/浅拷贝 编译器为我们提供的合成拷贝构造函数以及合成的拷贝赋值运算符都是浅拷贝.浅拷贝只是做简单的复制,如果在类的构造函数中new出了内存,浅拷贝只会简单的复制一份指向该内存的指针,而不会再开辟 ...
- TCP异常关闭研究分析
版权声明:本文由谢代斌原创文章,转载请注明出处: 文章原文链接:https://www.qcloud.com/community/article/108 来源:腾云阁 https://www.qclo ...
- 从 C# 崩溃异常 中研究页堆布局
一:背景 1.讲故事 最近遇到一位朋友的程序崩溃,发现崩溃点在富编辑器 msftedit 上,这个不是重点,重点在于发现他已经开启了 页堆 ,看样子是做了最后的挣扎. 0:000> !analy ...
- c++构造函数析构函数调用顺序
#include <iostream> using namespace std; class A { public: A () { cout<<"A 构造 " ...
- C++ 构造函数或析构函数调用虚函数
构造函数和析构函数中的虚函数 在执行基类构造函数时,对象的派生类部分是未初始化的.实际上,此时对象还不是一个派生类对象. 为 了适应这种不完整,编译器将对象的类型视为在构造或析构期间发生了变化.在基类 ...
- C++类的继承中构造函数和析构函数调用顺序例子
/*当建立一个对象时,首先调用基类的构造函数,然后调用下一个派生类的构造函数,依次类推,直至到达派生类次数最多的派生次数最多的类的构造函数为止.简而言之,对象是由“底层向上”开始构造的.因为,构造函数 ...
- C++中构造函数和析构函数调用的时机
今天看书忽然对这个地方有点模糊,尤其是析构函数在调用默认的析构函数和用户自己覆写的析构函数的时候有点意识模糊呢.写段代码总结下 #include <iostream> using name ...
随机推荐
- python学习 文件操作
一.python打开文件 #=====================python 文件打开方式 open()===================== # open(fileName,type) t ...
- 锁&锁与指令原子操作的关系 & cas_Queue
锁 锁以及信号量对大部分人来说都是非常熟悉的,特别是常用的mutex.锁有很多种,互斥锁,自旋锁,读写锁,顺序锁,等等,这里就只介绍常见到的, 互斥锁 这个是最常用的,win32:CreateMute ...
- Android点击效果
我们在开发网站时,会发现当我们添加<a/>标签后,标签有一个点击效果,比如颜色变化,这样开看起来用户体验会很棒,那么在我们的Android开发中如何加入这样的效果呢?本篇就为大家揭开它的神 ...
- poj3422 Kaka's Matrix Travels(最小费用最大流问题)
/* poj3422 Kaka's Matrix Travels 不知道 k次 dp做为什么不对??? 看了大牛的代码,才知道还可以这样做! 开始没有理解将a 和 a‘ 之间建立怎样的两条边,导致程序 ...
- 【原创】C#玩高频数字彩快3的一点体会
购彩风险非常高,本人纯属很久以前对数字高频彩的一点研究.目前已经远离数字彩,重点研究足球篮球比赛资料库和赛果预测. 这是一篇在草稿箱保存了1年多的文章,一直没发现,顺便修改修改分享给大家.以后会有更多 ...
- Oracle工具之DBNEWID
DBNEWID是Oracle提供的一个用于修改数据库DBID和DBNAME的工具. 在引进该工具之前,如果我们想修改数据库的数据库名,必须重建控制文件.但即便如此,也无法修改该数据库的DBID.众所周 ...
- 牛顿法与拟牛顿法学习笔记(三)DFP 算法
机器学习算法中经常碰到非线性优化问题,如 Sparse Filtering 算法,其主要工作在于求解一个非线性极小化问题.在具体实现中,大多调用的是成熟的软件包做支撑,其中最常用的一个算法是 L-BF ...
- Anliven - 解决问题的一些方法
How to resolve the problem? 获取基本的相关信息(后续处理问题的基础) 在怎样的背景环境下?发生了怎样的问题? 如果无法清楚地辨别或陈述问题的基本信息,那么,此时要面对的将 ...
- 让 jQuery UI draggable 适配移动端
背景: 在移动端,本人要实现对某个元素的拖动,想到使用 jQuery UI 的 draggable 功能.但是发现此插件的拖动只支持PC端,不支持移动端. 原因: 原始的 jQuery UI 里,都是 ...
- 用caffe跑自己的数据,基于WINDOWS的caffe
本文详细介绍,如何用caffe跑自己的图像数据用于分类. 1 首先需要安装过程见 http://www.cnblogs.com/love6tao/p/5706830.html 同时依据上面教程,生成了 ...