内存泄露的检测小程序

转载于: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;
 }

 
}

测试代码在附件中了, 没有实际移植到嵌入式系统跑过. 

posted @ 2018-01-30 14:55  _小百  阅读(812)  评论(0编辑  收藏  举报