注:不是原创。其实可以要Entry 加一个成员变量保存每次申请的内存大小,在Add中加进去
#include <iostream>
#include <map>
#include <string>
#include <cstring>
#include <vector>
using namespace std;
class Tracer
{
private:
class Entry
{
private:
const char * _file;
int _line;
public:
Entry(const char * file, int line) :_file(file),
_line(line) {}
Entry() :_line(0), _file(0){}
const char * File()const { return _file; }
int Line() const { return _line; }
};
class Lock
{
private:
Tracer & _tracer;
public:
Lock(Tracer & tracer) :_tracer(tracer)
{
_tracer.lock();
}
~Lock()
{
_tracer.unlock();
}
};
public:
Tracer();
~Tracer();
void Add(void * p, char const * file, int line);
void Remove(void * p);
void Dump();
static bool Ready;
private:
int _lockCount;
typedef map<void *, Entry>::iterator iter;
map<void *, Entry> _map;
private:
void lock() { _lockCount++; }
void unlock() { _lockCount--; }
};
bool Tracer::Ready = false;
Tracer::Tracer() :_lockCount(0)
{
Ready = true;
}
Tracer::~Tracer()
{
Ready = false;
Dump();
}
void Tracer::Dump()
{
if (_map.size() != 0)
{
cout << _map.size() << "memory leaks detected" << endl;
for (iter itor = _map.begin(); itor != _map.end(); ++itor)
{
const char * file = itor->second.File();
int line = itor->second.Line();
cout << file << "," << line << endl;
}
}
}
void Tracer::Add(void * p, char const * file, int line)
{
if (_lockCount > 0)
return;
Tracer::Lock lock(*this);
_map[p] = Entry(file, line);
}
void Tracer::Remove(void * p)
{
if (_lockCount > 0)
return;
Tracer::Lock lock(*this);
iter itor = _map.find(p);
if (itor != _map.end())
_map.erase(itor);
}
Tracer gNewTracer;
void * operator new(size_t size,const char * file,int line)
{
void * p = malloc(size);
if (Tracer::Ready)
gNewTracer.Add(p, file, line);
return p;
}
void operator delete(void * p, const char * file, int line)
{
if (Tracer::Ready)
gNewTracer.Remove(p);
free(p);
}
void * operator new(size_t size)
{
void * p = malloc(size);
if (Tracer::Ready)
gNewTracer.Add(p, "?", 0);
return p;
}
void operator delete(void * p)
{
if (Tracer::Ready)
gNewTracer.Remove(p);
free(p);
}
void* operator new [](size_t size, const char* file, int line)
{
void* p = malloc(size);
if (Tracer::Ready)
gNewTracer.Add(p, file, line);
return p;
}
void operator delete[](void* p, const char* file, int line)
{
if (Tracer::Ready)
gNewTracer.Remove(p);
cout << "delete[](void* p, const char* file, int line)" << endl;
free(p);
}
void* operator new[](size_t size)
{
void* p = malloc(size);
if (Tracer::Ready)
gNewTracer.Add(p, "?", 0);
return p;
}
void operator delete[](void* p)
{
if (Tracer::Ready)
gNewTracer.Remove(p);
cout << "delete[](void* p)" << endl;
free(p);
}
#define new new(__FILE__, __LINE__)
int main()
{
int *a = new int(3);
int * p = new int[3];
delete a;
}