virtual与析构函数引起我的悲剧
2013-02-02 09:13
141 查看
virtual与析构函数引起我的悲剧
场景: 定义一个接口类, 不同子类实现接口. 实现多态. 看下面代码
悲剧发生: 内存泄露了! 这么就简单的一段代码, 内存泄露了? 该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: 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;
相关文章推荐
- 一个简易查询引起的悲剧
- 基类的析构函数为何要声明为virtual
- 析构函数(Virtual)的原因
- 析构函数 private 、virtual的作用
- 基类的析构函数需要virtual
- virtual 析构函数的作用
- C++ 析构函数 使用virtual的原因
- virtual析构函数
- C++ 构造函数和析构函数与virtual关键字
- c++之Item7在多态基类中将析构函数声明为virtual
- C++中构造函数和析构函数(virtual)的执行顺序
- System.getProperty()引起的悲剧--您的主机中的软件中止了一个已建立的连接
- C++将多态基类的析构函数声明为virtual的作用
- 基函数的析构函数要加virtual
- 如果基类的析构函数不是virtual的,那么在派生类对象过期时,先调用自己的析构函数,接着会调用基类的析构函数吗?
- 构造函数与析构函数以及virtual
- 详解 C++ virtual 析构函数
- 为何virtual析构函数不能是protected?
- C++中基类的析构函数为什么要用virtual虚析构函数
- 当使用多态时,请为基类声明 virtual 析构函数