如何预防内存泄漏

一、内存泄漏的原因

我们的程序向系统申请分配了一块内存(new/malloc)给对象使用,程序使用完这块内存后没有释放delete/free),导致这个不使用的对象一直占据内存单元,造成系统将不能再把它分配给需要的程序。
内存泄露简单来说就是,内存分配与内存释放没有做到一对一的匹配

二、内存泄漏的危害

堆内存被不断的分配使用,没有及时回收,随着程序的运行,堆内存会慢慢的被消耗殆尽,当其他程序需要内存时,系统无法及时的分配合适的内存供其使用,将会造成程序崩溃。

三、如何预防内存泄漏

1、规范动态内存的使用,尽量避免不当用法;
2、及时检测到程序中有内存泄漏,并准确的定位到内存泄漏的具体位置(内存泄漏检测组件);

四、内存泄漏检测组件的实现原理

我们已经知道了内存泄漏的原因,那么内存泄露检测组件的关键就是:
1、内存的申请(new/malloc)与回收(delete/free)是否成对匹配

将系统的(new/malloc)与(delete/free)hook住,在自己实现的hook函数内部进行申请与回收的匹配计算;

2、定位到准确的内存泄露位置(具体到代码的哪一行)

1)c语言中有宏定义可以解决此问题:
	__LINE__  :当前程序行的行号,表示为十进制整型常量
	__FILE__  :当前源文件名,表示字符串型常量
2)__builtin_return_address(),返回当前函数的调用者的地址,通过地址可以得到具体的行号。

五、代码实现内存泄漏组件

编译的时候一定要加上 -g 参数

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

/*
1、用两个宏hook住系统的malloc/free,宏定义一定要在hook函数(malloc_hook、free_hook)之后,
    不然hook函数会一直递归下去(因为执行不到系统的malloc函数),导致段错误;
2、用申请出来的内存地址作为文件名,malloc_hook时,生成文件,将文件名行号等信息放在文件中,
    free_hook时,将同名的文件删掉(unlink()),并释放掉内存,剩下的文件就是没有被释放的内存信息;
3、不用__FILE__, __LINE__这两个c语言的宏,也可以用__builtin_return_address()实现,这个函数返回的是当前函数的调用者的地址,
    然后用addr2line方法分析出此地址对应的文件及行号,
    例:addr2line -f -e memory_leak -a 0x4006f7 (在终端执行),-e 可执行程序,-a 地址;
    __FILE__, __LINE__这两个宏应该也是通过这种方法实现的。
*/

void *malloc_hook(size_t size, char* file, int line)
{
    void *p = malloc(size);

    char buff[128] = {0};
    sprintf(buff, "./mem/%p.mem", p);//将申请到的内存地址作为文件名

    FILE *fp = fopen(buff, "w");
    fprintf(fp, "[+%s:%d]--> addr:%p, size:%ld\n", file, line, p, size);//将申请内存的信息存放在文件中:file文件中的line行,申请的内存地址为p,大小为size
    fflush(fp);

    fclose(fp);

    return p;
}

void free_hook(void *p, char* file, int line)
{
    char buff[128] = {0};
    sprintf(buff, "./mem/%p.mem", p);

    if (unlink(buff) < 0)   //文件不存在,说明内存被重复释放了
    {
        printf("double free: %p\n", p);
        return ;
    }

    free(p);
}

#define malloc(size) malloc_hook(size, __FILE__, __LINE__)
#define free(p) free_hook(p, __FILE__, __LINE__)

int main()
{
    void *p1 = malloc(10);
    void *p2 = malloc(20);

    p2 = p1;

    free(p2);
    return 0;
}```

有已经比较成熟的内存检测工具,比如mtrace/muntrace,大致用法如下,具体用法网上有很多自行查找
{
	mtrace();
	需要内存检测的代码段、、、
	muntrace();
}
这种方法的分析道的结果也是一些地址信息,还是需要用上述 3 所讲的工具进行分析,得到肉眼可见的调用位置
  • 4
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值