virtual与析构函数引起我的悲剧

本文探讨了在C++中使用虚拟析构函数的重要性。通过一个具体的案例分析,展示了当基类的析构函数未声明为虚函数时,派生类的资源无法正确释放,从而导致内存泄漏的问题。文章还提供了正确的代码实现方式。

virtual与析构函数引起我的悲剧


场景: 定义一个接口类, 不同子类实现接口. 实现多态. 看下面代码

// virtual与析构函数引起我的悲剧
// File.h
class MyInterface
{
public:
	virtual int Fun1() = 0;
	virtual int Fun2() = 0;
	virtual int Fun3() = 0;	
};
///////////////////////////////////////////
class MySubClass : public MyInterface
{
public:
	MySubClass();
	virtual ~MySubClass();
	virtual int Fun1();
	virtual int Fun2();
	virtual int Fun3();
private:
	unsigned char* m_pData;	
};

//////////////////////////////////////////////////////////////
// File.cpp
MySubClass::MySubClass()
{
	m_pData = new char[20];
}

MySubClass::~MySubClass()
{
	delete [] m_pData;
}

int MySubClass::Fun1()
{
	return 1;
}
int MySubClass::Fun2()
{
	return 2;
}

int MySubClass::Fun3()
{
	return 3;
}
///////////////////////////////////////////////////////////////////////////////
// Use.cpp
#include "File.h"
MyInterface* pMyInterface = new MySubClass;
pMyInterface->Fun1();
delete pMyInterface;


悲剧发生: 内存泄露了! 这么就简单的一段代码, 内存泄露了? 该delete的我都delete


排查: 调试发现MySubClass的析构函数没有调用.


原因: delete pMyInterface; 调用的是MyInterface类的编译器给的析构函数(因为我在MyInterface定义中没有给出析构函数). 不是多态吗? 应该先调用MySubClass的析构函数吗?

 很明显, 编译器给的MyInterface的析构函数没有virtual修饰, 所以delete pMyInterface并没有多态.

更悲剧的事情: 如果我是在上面代码上发现这个问题, 找原因可能一下子就可以找到了, 可是不是啊, 是在另外一个工程中发生了内存泄露, 

找啊找啊找啊, 用了我两天的时间啊........ 鬼才知道是这个基础的原因引起, 

总结教训: 
排查原因要分主次
1. 先从最基础的原因入手, 从最常见的错误原因入手. 例如上面说的原因; 例如new了, 没delete;


2. 在确保了不是1引起的, 再去看程序的逻辑流程. 例如虽然new了也对应delete了, 但是由于一些跳转引起了并没有调用delete.


3. 在排查程序的逻辑流程的时候, 单元测试要做好. 通常程序有好几个或者几十个单元模块组成, 这么多个模块扯在一起, 是模块实现问题还是模块调用问题? 谁知道. 

    如果你确保了某个单元模块的实现是绝对没问题的, 可以迅速排出很多原因的.


正确代码是:

// virtual与析构函数引起我的悲剧
// File.h
class MyInterface
{
public:
	MyInterface(){}
	virtual MyInterface(){}		// ----------------------就加多这两句-------------------------
	virtual int Fun1() = 0;
	virtual int Fun2() = 0;
	virtual int Fun3() = 0;	
};

class MySubClass : public MyInterface
{
public:
	MySubClass();
	virtual ~MySubClass();
	virtual int Fun1();
	virtual int Fun2();
	virtual int Fun3();
private:
	unsigned char* m_pData;	
};

// File.cpp
MySubClass::MySubClass()
{
	m_pData = new char[20];
}

MySubClass::~MySubClass()
{
	delete [] m_pData;
}

int MySubClass::Fun1()
{
	return 1;
}
int MySubClass::Fun2()
{
	return 2;
}

int MySubClass::Fun3()
{
	return 3;
}

// Use.cpp
#include "File.h"
MyInterface* pMyInterface = new MySubClass;
pMyInterface->Fun1();
delete pMyInterface;


评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值