内存泄露——不包含头文件类的析构函数不执行

来源:互联网 发布:七友软件 编辑:程序博客网 时间:2024/05/17 23:07

今天遇到一个很诡异的内存泄露,记录如下:

1.两个类,记为A,B。其中A有应指向B的指针;B也有指针成员,指向new出来的空间。两个类定义如下:

<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);"></span><pre name="code" class="cpp">1.1文件A.hclass B;class A{public:    ~A();public:    B * m_pB;...};1.2 文件A.cpp#include "A.h"A::~A(){    if(m_pB)    {        delete m_pB;        m_pB = NULL;     }}1.3 文件B.h<pre name="code" class="cpp"><pre name="code" class="cpp">class B{public:    B();    ~B();private:    int * m_p0;...};1.4 文件B.cpp#include "B.h"B::B(){    m_p0 = new int(NUM);}B::~B(){    if(m_p0)    {        delete m_p0;        m_p0 = NULL;    }}


<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">根据上述定义,可以看出:</span>

1)B类里有new的指针,因此需要自定义析构函数,否则会造成内存泄露;

2)A类中有B的指针(下面会用new来赋值),但A.h文件只是声明了B类,而不是包含B类的头文件。A.cpp文件也未包含B.h,因此也是看不到B类的定义的。

2.下面给出main函数:

</pre><pre name="code" class="cpp">#include "A.h"#include "B.h"int main(){    A * pA = new A;    A.m_pB = new B();    delete pA;}


上述代码会造成内存泄露!


3.分析:

     理论上说,执行delete pA;会调用A的析构函数,而A的析构函数又会调用B的析构函数,B的析构函数析构new出来的数组空间。然而实际上并非如此,上述代码会造成内存泄露。原因如下:

执行delete pA;会调用A类的析构函数,这步没有错。A类的析构函数会执行delete m_pB; 这步并不会调用B类的析构函数,原因在于A类的析构函数看不到B类的定义,所以也就不知道B类定义了自己的析构函数,它只释放了B类占用的空间(不包括B类里m_p0指针指向的空间)。因此造成内存泄露。

解决方法很简单:在A.cpp中包含头文件B.h。


4.总结:

    这个代码是在VS2010里写的,我不确定上述问题是C++语法的问题,还是VS的问题。有上面的分析我搞明白了delete所做的工作,delete一个指针p,p指向的对象的大小size肯定是知道的,那么delete的功能就是释放从p开始,大小为size的连线空间。

0 1
原创粉丝点击