有一个很著名的内存泄露检测工具Visual leak detected想必大家都不陌生,但今天我们可以自己写一个简易版的。哈哈,自己动手,丰衣足食有木有!!!
它的原理就是我们重载了操作符new和delete,当用new开辟空间的时候,就讲这块空间串到我们定义的结构体MEMNode形成的链表中,(这是老师的写法,在main程序结束时,用check_vld()函数检测有没有内存泄露)但我觉得,如果我们动态开辟了一个对象,在它的析构函数里用delete释放的话,这种方法就不太可行。因为析构函数只有到return时才会被调用(在check_vld()函数之前)。检测结果就不准确。由此我想到,可以将这个结构体该为C++中的类class MEMNode,并将其指针也封装为一个类PMEMNode,然后定义一个PMEMNode的全局静态成员(它会在主函数之前被构造,主函数结束后析构)。并将check_vld()的代码放在他的析构函数中。
废话不多说,代码在下面:
vld.h:
#pragma once
#include <iostream>
using namespace std;
class MemNode {
friend void* operator new(size_t sz, char *filename, int line);
public:
MemNode(int s = 0,char *pf = NULL, int l = 0,class MemNode *pl=NULL)
:size(s),file(pf),line(l),link(pl)
{}
~MemNode()
{}
void set(int sz, char *pf, int l, class MemNode *pl)
{
size = sz;
file = pf;
line = l;
link = pl;
}
void setlink(MemNode *pl)
{
link = pl;
}
int getsize()
{
return size;
}
char *getfile()
{
return file;
}
int getline()
{
return line;
}
MemNode *getlink()
{
return link;
}
private:
int size;
char *file;
int line;
class MemNode *link;
};
void check_vld();
class pMemNode {
public:
pMemNode(MemNode *ptr=NULL):p(ptr){}
~pMemNode()
{
check_vld();
}
MemNode *getptr()
{
return p;
}
void setptr(MemNode *ptr)
{
p = ptr;
}
private:
MemNode *p;
};
static pMemNode _AfxMem;
void* operator new(size_t sz,char *filename,int line)
{
void *result=NULL;
int total_size = sz + sizeof(MemNode);
MemNode *p = new MemNode[total_size];
p->set(sz, filename, line, NULL);
if (_AfxMem.getptr() == NULL)
{
_AfxMem.setptr(p);
}
else
{
p->setlink(_AfxMem.getptr());
_AfxMem.setptr(p);
}
result = _AfxMem.getptr()+1;
return result;
}
void operator delete(void *ptr)
{
if(_AfxMem.getptr()==NULL)
{
return;
}
if(ptr==NULL)
{
return;
}
MemNode *p;
if (_AfxMem.getptr()+1 == ptr)
{
p = _AfxMem.getptr();
_AfxMem.setptr(p->getlink());
delete p;
}
else
{
p = _AfxMem.getptr();
while (p->getlink() != NULL && p->getlink()+1!=ptr)
{
p = p->getlink();
}
if (p->getlink() != NULL)
{
MemNode *q = p->getlink();
p->setlink(q->getlink());
delete q;
}
}
}
void check_vld()
{
if (_AfxMem.getptr() == NULL)
{
cout << "No memory Leaks detected." << endl;
}
else
{
MemNode *p = _AfxMem.getptr();
cout << "WARNING: Visual Leak Detector detected memory leaks!" << endl;
while (p != NULL)
{
printf("At %p: %d Bytes\n", p + 1, p->getsize());
printf("file: %s, line: %d\n", p->getfile(), p->getline());
p = p->getlink();
}
}
}
Main.cpp:
#include <iostream>
#include <string>
#include "vld.h"
using namespace std;
class Test
{
public:
Test(char *str)
{
int a = strlen(str) + 1;
ch = new(__FILE__, __LINE__) char[a];
//strcpy(ch, str);
}
~Test()
{
delete[]ch;
ch = NULL;
}
private:
char *ch;
int a;
double b;
char c;
};
int main()
{
//VLD vld;
int a = 10;
Test t("hello");
//int *p = new(__FILE__,__LINE__) int(10);
//double *q = new(__FILE__,__LINE__) double(12.34);
Test *s = new(__FILE__,__LINE__) Test("hello");
//delete p;
//delete q;
//check_vld();
return 0;
}