马上注册,结交更多好友,享用更多功能^_^
您需要 登录 才可以下载或查看,没有账号?立即注册
x
本帖最后由 andalousie 于 2014-2-25 08:41 编辑
我在书上看到可以通过重载new和delete运算符实现跟踪内存泄漏。这里把我自己的例子发布出来。
用于测试的文件test.cpp
#include <iostream>
#include <cstdlib>
#if !defined NDEBUG
#include "Tracer.h"
#define new new (__FILE__, __LINE__)
Tracer NewTrace;
#endif
#include <cstring>
/************************************************
* info -- A class to hold information. *
* *
* Note: *
* Because someone is walking all over our *
* memory and destroying our data, we *
* have put two guards at the beginning *
* and end of our class. If someone *
* messes with us these numbers will *
* be destroyed. *
* *
* Member functions: *
* set_data -- Store a string in our data. *
* get_data -- Get the data string. *
* check_magic -- Check the magic numbers. *
************************************************/
// Magic numbers for the start and end of the
// data in the class info
const int START_MAGIC = 0x11223344;
const int END_MAGIC = 0x5567788;
class info
{
private:
// Magic protection constant
const int start_magic;
// String to be stored
char data[30];
// Magic protection constant
const int end_magic;
public:
info(void):
start_magic(START_MAGIC),
end_magic(END_MAGIC)
{}
// Copy constructor defaults
// Assignment operator defaults
// Destructor defaults
// Store some data in the class
void set_data(
// Data to be stored
const char what[]
)
{
strcpy(data, what);
}
// Get the data from the class
char *get_data(void)
{
return (data);
}
// Verify that the magic
// numbers are correct
void check_magic(void)
{
if ((start_magic != START_MAGIC) ||
(end_magic != END_MAGIC))
{
std::cout <<
"Info has lost its magic\n";
}
}
};
/************************************************
* new_info -- Create a new version of the *
* info class. *
************************************************/
struct info *new_info(void)
{
struct info *result; // Newly created result.
/* result = (struct info *)
malloc(sizeof(struct info));
// Make sure the structure is clear
memset(result, '\0', sizeof(result));*/
result = new info; // Use C++ new rather than C malloc
return (result);
}
int main()
{
// An info class to play with
class info *a_info = new_info();
a_info->set_data("Data");
a_info->check_magic();
return (0);
}
测试结果*** Memory leak(s)
0x11223344: ptr/main.cpp, line 82
通过测试发现,在代码的第82行,也就是红色字体的,内存没有被释放。
这个代码本来是一个教学代码,如果使用绿色字体部分,而不是红色字体部分,就会输出
Info has lost its magic()
原因很简单,我们使用C语言形式的malloc分配空间不会调用构造函数,然后雪上加霜地用memset来将类置0……
对于这种问题,我只能给出一个我认为还算过得去的方案,就是使用智能指针。
我们可以自己写一个auto_ptr类,来用析构函数实现其内容的销毁。#if !defined (AUTOPTR_H)
#define AUTOPTR_H
//-------------
// Auto pointer
//-------------
template<class T>
class auto_ptr
{
template<class U> struct auto_ptr_ref
{
auto_ptr<U> & _ap;
auto_ptr_ref (auto_ptr<U> & p) : _ap (p) {}
};
public:
typedef T element_type;
explicit auto_ptr (T * p = 0) : _p (p) {}
// "transfer" constructor
auto_ptr (auto_ptr & pSrc)
{
_p = pSrc._p;
pSrc._p = 0;
}
auto_ptr & operator= (auto_ptr & pSrc)
{
reset (pSrc.release ());
return *this;
}
#if 0 // not in this version of the compiler
// "transfer" from derived class
template<class U>
auto_ptr (auto_ptr<U> & pSrc)
{
_p = pSrc._p; // implicit cast
pSrc._p = 0;
}
// assignment of derived class
template<class U>
auto_ptr & operator= (auto_ptr<U> & pSrc)
{
if (this != &pSrc)
{
_p = pSrc._p;
pSrc._p = 0;
}
return *this;
}
#endif
~auto_ptr () { delete _p; }
T & operator* () const { return *_p; }
T * operator-> () const { return _p; }
T * get () const { return _p; }
T * release ()
{
T * tmp = _p;
_p = 0;
return tmp;
}
void reset (T * p = 0)
{
if (p != _p)
{
delete _p;
_p = p;
}
}
auto_ptr (auto_ptr_ref<T> apr)
: _p (apr._ap.release ())
{}
template<class U>
operator auto_ptr_ref<U> ()
{
return auto_ptr_ref<U> (*this);
}
template<class U>
operator auto_ptr<U> ()
{
return auto_ptr<U> (release ());
}
private:
T * _p;
};
#endif
而把结构体的内容改成struct info *new_info(void)
{
auto_ptr<info> result(new info);
return (result.release());
}
在return之后就会自动调用auto_ptr类的析构函数。至于形参new info,其实在使用以后系统就会将其释放,所以我认为没有影响。或者大家以可以使用<memory>头文件里面的std::auto_ptr,这样就用不着自己写了。
如果有其他好的解决方案,请回复。
|