找回密码
 注册
搜索
查看: 1871|回复: 7

[讨论] 内存泄露的检测小程序

[复制链接]
发表于 2009-11-8 16:41:13 | 显示全部楼层 |阅读模式
通过封装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;
        }

       
}

测试代码在附件中了, 没有实际移植到嵌入式系统跑过.
【文件名】:09118@52RD_console.rar
【格 式】:rar
【大 小】:185K
【简 介】:
【目 录】:
发表于 2009-11-9 10:18:40 | 显示全部楼层
学习。[em08][em09]
点评回复

使用道具 举报

发表于 2009-11-9 21:42:14 | 显示全部楼层
用lint吧!
点评回复

使用道具 举报

发表于 2010-5-24 11:25:51 | 显示全部楼层
学习了……
点评回复

使用道具 举报

发表于 2010-5-27 11:52:04 | 显示全部楼层
好多智能机存在这个问题. 有一些山寨的高仿智能机,特别是仿HTC的,存在这个问题.
点评回复

使用道具 举报

发表于 2010-5-27 18:31:03 | 显示全部楼层
很好  学习了
点评回复

使用道具 举报

发表于 2010-5-28 18:58:15 | 显示全部楼层
蛮有学习的意义的。
点评回复

使用道具 举报

发表于 2010-7-28 22:30:05 | 显示全部楼层
支持免费
本文来自:我爱研发网(52RD.com) - R&D大本营
详细出处:http://www.52rd.com/bbs/Detail_RD.BBS_174800_38_1_1.html
点评回复

使用道具 举报

高级模式
B Color Image Link Quote Code Smilies

本版积分规则

Archiver|手机版|小黑屋|52RD我爱研发网 ( 沪ICP备2022007804号-2 )

GMT+8, 2024-10-9 00:41 , Processed in 0.053934 second(s), 18 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表