内存泄露的检测小程序
转载于:http://www.52rd.com/bbs/Dispbbs.asp?BoardID=38&ID=172660
通过封装malloc函数来实现, 抛砖引玉, 哪位大侠有更好的方法可以拿出来一起分享一下吧~~
原理:原来系统中可能存在大量的malloc分配内存的地方, 通过封装后可以记录下调用malloc的文件名和行数. 分配内存的时候把分配到的内存首地址放到链表中. 如果这段内存被释放再从链表中拿出来. 这样可以通过打印链表内容发现所有未释放的内存. 可以通过比较两个时间段的链表内容来判断哪些内存在偷偷地泄露, 应该还是比较明显滴... 缺点就是要额外分配空间存储链表. 如果有shell直接打印,如果没有shell就写文件吧...
用VC6.0环境
先在头文件stdafx.h中定义宏
#define malloc(size) malloc_ext(size,__FILE__, __LINE__)
#define free(p) free_ext(p,__FILE__, __LINE__)
void * malloc_ext(size_t size,const char *name, unsigned int line);
void free_ext(void * p,const char *name, unsigned int line);
函数声明
struct record * add_record(struct record *head, unsigned int addr, unsigned int line, const char *name);
int delete_record(struct record *head, unsigned int addr);
void show_record(void);
单向链表结构
/*文件路径名长度,可以根据需要修改*/
#define patch_len 50
struct record
{
char name[patch_len+1];
unsigned int line;
unsigned int addr;
struct record *next;
};
StdAfx.cpp文件中
先undef掉自己定义的宏
/*在此文件中去掉malloc的宏定义,使用系统提供的malloc函数*/
#ifdef malloc
#undef malloc
#endif
#ifdef free
#undef free
#endif
再重新包含系统的头文件
#include "malloc.h", 这样下面代码中用的就是系统的malloc free函数了
/*定义未释放内存链表头节点*/
struct record* record_list = 0;
void * malloc_ext(size_t size,const char *name,unsigned int line)
{
void *p = NULL;
p = malloc(size);
if(p != NULL)
{
record_list = add_record(record_list, (unsigned int)p, line, name);
}
return p;
}
void free_ext(void * p,const char *name, unsigned int line)
{
if (p == NULL)
{
printf("can\'t free a null pointer");
return;
}
delete_record(record_list, (unsigned int)p);
free(p);
}
record * add_record(struct record *head, unsigned int addr, unsigned int line, const char *name)
{
struct record *m = NULL;
struct record *n = NULL;
if(head == NULL)
{
head = (struct record*)malloc(sizeof(struct record));
head->addr = addr;
head->line = line;
memcpy(head->name, name, patch_len);
head->name[patch_len] = \'\\0\';
head->next = NULL;
return head;
}
m = head;
while(m->next != NULL)
{
m = m->next;
}
n = (struct record*)malloc(sizeof(struct record));
n->addr = addr;
n->line = line;
memcpy(n->name, name, patch_len);
n->name[patch_len] = \'\\0\';
n->next = NULL;
m->next = n;
m = n;
return head;
}
int delete_record(struct record *head, unsigned int addr)
{
struct record *m = NULL;
struct record *n = NULL;
if(head == NULL)
{
printf("warning: have been freed before!!");
}
m = n = head;
if(head->next == NULL)
{
if(n->addr == addr)
{
free(head);
record_list = head = NULL;
}
return 1;
}
n = m->next;
while(n != NULL)
{
if(n->addr == addr)
{
m->next = n->next;
free(n);
return 1;
}
m = m->next;
n = n->next;
}
return 1;
}
/*根据各自的系统打印未释放内存链表内容,或者写入文件*/
void show_record(void)
{
struct record *p = NULL;
struct record *head = NULL;
int i = 0;
head = record_list;
if(head == NULL)
{
printf("list is enpty!\\n");
return;
}
p = head;
printf("memory list without free:\\n");
while(p != NULL)
{
printf("Node %d is:\\n", ++i);
printf("path = %s\\n", p->name);
printf("line = %u\\n", p->line);
printf("addr = 0x%x\\n\\n\\n", p->addr);
p = p->next;
}
}
测试代码在附件中了, 没有实际移植到嵌入式系统跑过.