内存泄漏检测相关内容

简介: 内存泄漏检测相关内容

1 拦截 malloc free函数

通过拦截 malloc,free函数,然后以宏定义的方式,改造malloc, free: malloc的时候根据指针地址写一个文件,
free的时候根据指针地址删除这个文件。最后根据留下的文件就可以知道哪个new没有释放内存了。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
void *_malloc(size_t size, const char *filename, int line) {
   
   

    void *ptr = malloc(size); 

    char buff[128] = {
   
   0};
    sprintf(buff, "./mem/%p.mem", ptr);

    FILE *fp = fopen(buff, "w");
    fprintf(fp, "[+]addr: %p, filename: %s, line: %d\n", ptr, filename, line);

    fflush(fp);
    fclose(fp);


    return ptr;
}

void _free(void *ptr, const char *filename, int line) {
   
   

    char buff[128] = {
   
   0};
    sprintf(buff, "./mem/%p.mem", ptr);

    if (unlink(buff) < 0) {
   
    // filename no exist;
        printf("double free: %p\n", ptr);
        return ;
    }

    return free(ptr);
}


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

方法1的弊端是,最好是用在一个.c文件中,如果文件较多的话就不太适用。

2 hook malloc/free

同方法1,不过这里使用的是dlsym 来hook malloc/free来代替方法1,通过caller = __builtin_return_address(0)获取
调用者,就算是在不同的文件里也适用

typedef void *(*malloc_t)(size_t size);
typedef void *(*free_t)(size_t size);

malloc_t malloc_f = NULL;
free_t free_f = NULL;

int enable_malloc_hook = 1;
int enable_free_hook = 1;
void *malloc(size_t size){
   
   
    void p;
    if(enable_malloc_hook){
   
    // 避免 递归调用 加标志enable_malloc_hook
        enable_malloc_hook = 0;
        p = malloc_f(size);
        printf("malloc\n");  

        void  caller = __builtin_return_address(0);
        printf("caller = %p\n", caller);

        char buff[128] = {
   
   0};
        sprintf(buff, "./%p.mem", p); // filename
        FILE *fp = fopen(buff, "w");
        fprintf(fp, "[+]%p:%d addr: %p, size: %ld \n", caller,  __LINE__, p, size);  //这里的 LINE 不符合要求
        ///////////////
        /////////////// 用这个命令找到有malloc没有free的地方: addr2line -f -e 应用程序 -a caller(指针地址) ==> 函数+line
        ///////////////
        fflush(fp);
        enable_malloc_hook = 1;
    } else {
   
   
        p = malloc_f(size);
    }
    return p;
}
void free(void *ptr){
   
   
    if(enable_free_hook){
   
   
        enable_free_hook = 0;

        char buff[128] = {
   
   0};
        sprintf(buff, "./%p.mem", ptr); // filename
        if(unlink(buff) < 0){
   
     // file not exist;    double free
            printf("double free: %p\n", ptr);
            //return ptr;
        }

        enable_free_hook = 1;
    } else {
   
   
        free_f(reinterpret_cast<size_t>(ptr));
    }
    printf("free\n");
    //return ptr;
}
void Init_hook(void){
   
   
    if(malloc_f == NULL){
   
   
        malloc_f = (malloc_t)dlsym(RTLD_NEXT, "malloc"); //这里得到函数调用的入口
    }
    if(free_f == NULL){
   
   
        free_f = (free_t)dlsym(RTLD_NEXT, "free");
    }
}

int main(){
   
   
    Init_hook(); 
    void *p1 = malloc(5);
    void *p2 = malloc(15);
    void *p3 = malloc(25);
    free(p1);
    free(p2);
    return 0;
}

3 封装底层的malloc free

用更加底层的函数申请内存,释放内存
libc中含有 malloc free ,所以它们不是系统调用
所以可以参考如下:

extern void * __libc_malloc(size_t size)
extern void * __libc_free(void * p)

void * malloc(size_t size) {
   
   
    __libc_malloc(x);  //  这里相当于用了一个跟家底层的接口
}

其它部分类似方法2

4 使用 bpftrace工具

bpftrace要求 linux5.4及以上支持
bpftrace // 可以不用管对方的代码 ,在内核允许的情况下
uprobe 可以挂函数名(内存)、网络、进程调度、内核执行流程等都可以的
在目标程序memleak同级目录下touch一个mem.bt的文件,输入下面的内容,

uprobe:/lib/x86_64-linux-gnu/libc.so.6:malloc
/comm == "memleak" /
{
   
   
    printf("malloc\n");
}
uprobe:/lib/x86_64-linux-gnu/libc.so.6:free
/comm == "memleak" /
{
   
   
    printf("free\n");
}

然后:
1 一个终端运行 bpftrace mem.bt
2 接着另一个终端 ./memleak (memleak 是类似标题1中的程序名)
memleak.c // gcc memleak.c -o memleak
int main(){

            void *p1 = malloc(5);
            void *p2 = malloc(15);
            void *p3 = malloc(25);
            free(p1);
            free(p2);
            return 0;
        }

如下图:可以查内存泄漏了malloc与 free 的数量不一样,说明有内存没有释放
在这里插入图片描述

5 还是bpf工具,监测进程

稍稍改变一下测试程序

int main() {
   
   

    while(1){
   
   
        void *p1 = malloc(5);
        void *p2 = malloc(5);
        void *p3 = malloc(5);


        free(p1);
        free(p2);
        sleep(1);
    }
}

运行上面的测试程序,查看进程id
在这里插入图片描述
对应进程id是111806,touch一个mempid.bt修改内容如下

uprobe:/lib/x86_64-linux-gnu/libc.so.6:malloc
/pid == 111806/
{
   
   
    printf("malloc\n");
}

uprobe:/lib/x86_64-linux-gnu/libc.so.6:free
/pid == 111806/
{
   
   
    printf("free\n");
}

运行测试程序:bpftrace mempid.bt,可得如下输出结果
在这里插入图片描述
通过过bpftrace方法查到内存泄露的情况,适用于测试看不到源码的程序。
文章参考与<零声教育>的C/C++linux服务期高级架构系统教程学习:链接

相关文章
|
6天前
|
开发工具 Swift iOS开发
【Swift开发专栏】Swift中的内存泄漏检测与修复
【4月更文挑战第30天】本文探讨了Swift中的内存泄漏问题,尽管有ARC机制,但仍需关注内存管理。文章分为三部分:内存管理基础知识、检测方法和修复技巧。了解ARC原理和循环引用陷阱是防止内存泄漏的关键。检测方法包括使用Xcode内存调试器、LeakSanitizer和性能分析工具。修复技巧涉及打破循环引用、使用弱/无主引用及手动管理内存。理解这些对优化应用性能和稳定性至关重要。
|
6天前
|
缓存 监控 Python
在Python中,如何检测和处理内存泄漏?
【2月更文挑战第7天】【2月更文挑战第18篇】在Python中,如何检测和处理内存泄漏?
|
6天前
|
安全 Linux 编译器
内存泄漏检测组件的分析与实现(linux c)-mtrace工具使用
内存泄漏产生原因 在堆上使用malloc/remalloc/calloc分配了内存空间,但是没有使用free释放对应的空间。
79 0
|
6天前
|
Java C++
动手实现内存泄漏检测组件
动手实现内存泄漏检测组件
43 1
|
6天前
使用mtrace进行内存泄漏检测
使用mtrace进行内存泄漏检测
77 1
|
6天前
|
IDE Linux 开发工具
内存泄漏检测工具Valgrind:C++代码问题检测的利器(一)
内存泄漏检测工具Valgrind:C++代码问题检测的利器
180 0
|
2天前
|
算法 Java Python
【Python 的内存管理机制专栏】Python 内存管理实战:性能优化与内存泄漏检测
【5月更文挑战第18天】Python内存管理关乎程序性能与稳定性。优化包括避免过多临时对象,如优化列表推导式减少对象创建。警惕循环引用造成的内存泄漏,如示例中的Node类。使用`gc`模块检测泄漏,通过`gc.set_debug(gc.DEBUG_LEAK)`和`gc.collect()`获取信息。实践中需持续分析内存使用,优化算法、数据结构和资源释放,以提升程序质量与效率。
【Python 的内存管理机制专栏】Python 内存管理实战:性能优化与内存泄漏检测
|
6天前
|
Dart 前端开发 Java
【Flutter前端技术开发专栏】Flutter中的内存泄漏检测与解决
【4月更文挑战第30天】本文探讨了Flutter应用中的内存泄漏检测与解决方法。内存泄漏影响性能和用户体验,常见原因包括全局变量、不恰当的闭包使用等。开发者可借助`observatory`工具或`dart_inspector`插件监测内存使用。解决内存泄漏的策略包括避免长期持有的全局变量、正确管理闭包、及时清理资源、妥善处理Stream和RxDart订阅、正确 disposal 动画和控制器,以及管理原生插件资源。通过这些方法,开发者能有效防止内存泄漏,优化应用性能。
【Flutter前端技术开发专栏】Flutter中的内存泄漏检测与解决
|
6天前
|
数据可视化 Java 测试技术
【Go语言专栏】Go语言中的内存泄漏检测与修复
【4月更文挑战第30天】Go语言内存泄漏详解:概念、原因、检测与修复。内存泄漏由忘记释放内存、循环引用等引起,Go通过垃圾回收机制管理内存,但仍有泄漏风险。检测方法包括pprof、可视化工具、代码审查和单元测试。修复策略涉及优化代码、使用defer、减少全局变量、弱引用及及时释放资源。实践案例分析有助于理解和解决问题。了解内存管理,防止泄漏,提升Go应用性能和稳定性。
|
6天前
|
缓存 Linux iOS开发
【C/C++ 集成内存调试、内存泄漏检测和性能分析的工具 Valgrind 】Linux 下 Valgrind 工具的全面使用指南
【C/C++ 集成内存调试、内存泄漏检测和性能分析的工具 Valgrind 】Linux 下 Valgrind 工具的全面使用指南
77 1