逝水流年

This is a blog to record my life, my work, my feeling …

Imcomplete Class Type Delete(不完整类类型的删除)

当delete不完整类类型对象的时候,不会调用对象的析构函数,导致内存泄漏。所以要避免delete 不确定类型。

首先解释下不完整类类型Imcomplete class type:只见声明不见定义的类、结构体或是联合体;相对应的就是complete type,就是编译器可以确定的类型。

下面举例说明:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//delete_object.h
class CObject;
void delete_object(CObject* pObj); //p为imcomplete type
//delete_object.cpp
void delete_object(CObject* pObj) {delete pObj;}
//CObject.h
class CObject
{
    //destructor
    ~CObject()
    {
        //destructor called.
    }
}
//main file
#include "delete_object.h"
#include "CObject.h"
int main(int argc, char[] argv)
{
    CObject* pObj = new CObject();
    delete_object(pObj);
}

这里的pObj对象在delete的时候就是不确定对象,编译器不知道它的类型,无法调用析构函数,最终导致内存泄漏。解决的最简单的方法,就是在delete_object.cpp文件中增加#include “CObject.h”语句即可。

我们这里要重点介绍的是boost库中的使用的方法,方法使用的非常巧妙。整理如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
//utiles.h
template<typename T>;
inline void checked_delete(T * x)
{
    // intentionally complex - simplification causes regressions
    typedef char type_must_be_complete[ sizeof(T)? 1: -1 ];
    (void) sizeof(type_must_be_complete);
    delete x;
}
template<typename T>;
inline void checked_arraydelete(T * x)
{
    // intentionally complex - simplification causes regressions
    typedef char type_must_be_complete[ sizeof(T)? 1: -1 ];
    (void) sizeof(type_must_be_complete);
    delete[] x;
}
template<typename T>;
struct checked_deleter
{
    typedef void result_type;
    typedef T * argument_type;
    void operator()(T * p) const
    {
        checked_delete(p);
    }
};
template<typename T>;
struct checked_arraydeleter
{
    typedef void result_type;
    typedef T * argument_type;
    void operator()(T * p) const
    {
        checked_arraydelete(p);
    }
};
//main file
//#include "delete_object.h"
#include "CObject.h"
#include "utiles.h"
int main(int argc, char[] argv)
{
    CObject* pObj = new CObject();
    //delete_object(pObj);
    checked_deleter<CObject>;(p);
}

既能在静态编译时监测出delete是否有问题,也可以安全的删除,不用再担心内存泄漏了!

Comments