什么是内存泄漏。检查内存泄漏的工具和方法有哪些,其原理是?

文章介绍了两种内存泄漏检测的方法。第一种利用mtrace和MALLOC_TRACE环境变量进行追踪,但虚拟内存地址无法直接用于addr2line。第二种方法是通过宏定义,在分配和释放内存时记录信息,简化了查找内存泄漏的步骤。
摘要由CSDN通过智能技术生成

内存泄漏:内存泄漏是由于内存分配与内存释放不匹配所引起的。

  1. 手写内存泄漏检测组件
    方法一:使用mtrace,但需要重启程序
    思路:设置环境变量 export MALLOC_TRACE=“xxx/mem.txt”, xxx表示你希望存放的路径,然后在程序的开头加上mtrace(),在末尾加上muntrace()
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <mcheck.h>

int main() {
    mtrace();
    int *p1 = (int*)malloc(5);
    int *p2 = (int*)malloc(15);

    free(p1);
    muntrace();

    return 0;
}

编译时需要加上-g选项

mem.txt中的内容为:

= Start
@ ./a.out:[0x5555555551c4] + 0x555555559690 0x5
@ ./a.out:[0x5555555551d2] + 0x5555555596b0 0xf
@ ./a.out:[0x5555555551e2] - 0x555555559690
= End

使用addr2line -f -e a.out -a xxx, xxx为怀疑内存泄漏的地址,使用该命令可以找到是程序中的哪个函数的哪一行发生了内存泄漏。

但是0x5555555551c4,为虚拟内存中的地址,无法使用addr2line,所以需要在程序中使用dladdr1函数将将地址转换为.elf中的符号信息。

使用完后将环境变量设置回来 export MALLOC_TRACE=""

具体实现:https://zhuanlan.zhihu.com/p/554448993

总的来说方案一的实现觉复杂,笔者推荐方案二。

方案二:宏定义
方案一还需要自己找出内存泄漏的地址,而使用宏定义即可跳过这一步。
思路:
● 使用宏定义,调用malloc后,以返回的指针指向的地址创建文件,并写入其在代码中的多少行等相关信息;
● 在调用free之前,使用unlink函数删除目录项,并且减少一个链接数。
● 执行完后,剩下的那个文件名即为内存泄漏的地址。

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

#define ENABLE_MEM 1

void * _malloc(size_t sz, const char * file, int line) {
    void * p = malloc(sz);

    char buff[256] = {0};
    sprintf(buff, "%p.mem", p);
    FILE* fp = fopen(buff, "w"); // 以返回的指针指向的地址创建文件

    // 填写相关信息
    fprintf(fp, "+[%s:%d] addr:%p, size: %lu byte(s)\n", file, line, p, sz);
    fflush(fp);
    fclose(fp);

    return p;
}

void _free(void * ptr) {
    char buff[256] = {0};
    sprintf(buff, "%p.mem", ptr);
    
    if (unlink(buff) < 0) {
        printf("Doule free: %p\n", ptr);
        return ;
    }

    free(ptr);
} 

#if ENABLE_MEM

#define malloc(size) _malloc(size, __FILE__, __LINE__)
#define free(p) _free(p);

#endif


int main() {
    int *p1 = (int*)malloc(5);
    int *p2 = (int*)malloc(15);

    free(p1);

    return 0;
}
C++内存泄漏检测原理+实例源码下载,是一个跨平台的C++ 内存泄漏检测器的源程序,一个主要缺陷是不支持多线程。分配内存时不进行文件名复制,而只是保存其指针;效率较高(编译debug_new.cpp  时有效;参见文件中的注释)   我本人认为,debug_new目前的一个主要缺陷是不支持多线程。对于某一特定平台,要加入多线程支持并不困难,难就难在通用上(当然,条件编译是一个办法,虽然不够优雅)。   等到C++标准中包含线程模型时,这个问题也许能比较完美地解决吧。另一个办法是使用像boost这样的程序库中的线程封装类,不过,这又会增加对其它库的依赖性--毕竟boost并不是C++标准的一部分。如果项目本身并不用boost,单为了这一个目的使用另外一个程序库似乎并不值得。因此,我自己暂时就不做这进一步的改进了。   另外一个可能的修改是保留标准operator new的异常行为,使其在内存不足的情况下抛出异常(普通情况)或是返回NULL(nothrow情况),而不是像现在一样终止程序运行(参见debug_new.cpp 的源代码)。这一做法的难度主要在于后者:我没想出什么方法,可以保留 new(nothrow) 的语法,同时能够报告文件名和行号,并且还能够使用普通的new。不过,如果不使用标准语法,一律使用debug_new和debug_new_nothrow的话,那还是非常容易实现的。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值