内存泄漏检测组件的实现

简介: 内存泄漏检测组件的实现
  1. 通过宏定义来包装 mallocfree 函数,以便在每次内存分配和释放时记录相关信息,如文件名和行号。这使得你能够跟踪哪个函数在哪里分配和释放内存。
#define _GNU_SOURCE
#include <dlfcn.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <link.h>
// 方式一:宏定义
void *_malloc(size_t size, char *filename,int line) {
    void *ptr = malloc(size);
    char file[128] = {0};
    sprintf(file ,"./mem/%p.mem" ,ptr);
    FILE *fp = fopen(file ,"w");//w小写
    fprintf(fp, "[+]addr: %p filename: %s line: %d\n",ptr,filename,line);
    fflush(fp);
    fclose(fp);
    return ptr;
}
void _free(void *ptr, char *filename,int line) {
    char file[128] = {0};
    sprintf(file,"./mem/%p.mem",ptr);
    if(unlink(file) < 0){//unlink用于在文件系统中删除指定的文件
        printf("double free %p\n",ptr);
        return;
    }
    return free(ptr);
}
// __FILE__ 获取文件名
// __LINE__ 获取函数执行的行号
#define malloc(size)   _malloc(size, __FILE__,__LINE__)
#define free(ptr)      _free(ptr, __FILE__,__LINE__)
int main(void) {
    init_hook();
    void *p1 = malloc(8);
    void *p2 = malloc(16);
    void *p3 = malloc(32);
    free(p1);
    free(p2);
    return 0;
}

编译执行:

表示在memleak.c 文件中, 第149行出现内存泄漏问题。

2.通过使用hook方法来重定向 mallocfree 函数, 与此同时通过__builtin_return_address()函数的返回值结合(*caller) 命令: addr2line -f -e ./程序名 -a 返回值(caller) 查看内存泄露的程序及具体行数。

#define _GNU_SOURCE
#include <dlfcn.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <link.h>
//方式二:hook
// gcc -o memleak memleak.c -g -ldl
// addr2line -f -e ./memleak -a 0x400b38(返回值)
typedef void *(*malloc_t)(size_t size);
malloc_t malloc_f = NULL;
typedef void (*free_t)(void *ptr);
free_t free_f = NULL;
int enable_malloc_hook = 1;
int enable_free_hook = 1;
void *COnvertToELF(void *addr) {
  Dl_info info;
  struct link_map *link;
  dladdr1(addr, &info, (void**)&link,RTLD_DL_LINKMAP);
  return (void*)((size_t)addr - link->l_addr);
}
void *malloc(size_t size) {
  void *ptr = NULL;
  if (enable_malloc_hook) {
    enable_malloc_hook = 0;
    ptr = malloc_f(size);
  // main --> f1() --> f2() --> f3() { __builtin_return_address(0)  }
    void *caller = __builtin_return_address(0);
    char filename[128] = {0};
    sprintf(filename, "./mem/%p.mem", ptr);
    FILE *fp = fopen(filename, "w");
    fprintf(fp, "[+] caller: %p, addr: %p, size: %ld\n",
       COnvertToELF(caller), ptr, size);
    fflush(fp);
    enable_malloc_hook = 1;
  } else {
    ptr = malloc_f(size);
  }
  return ptr;
}
void free(void *ptr) {
  if (enable_free_hook) {
    enable_free_hook = 0;
        char file[128] = {0};
    sprintf(file, "./mem/%p.mem", ptr);
    if (unlink(file) < 0) { // filename no exist;
      printf("double free: %p\n", ptr);
      return ;
    }
    free_f(ptr);
    enable_free_hook = 1;
  } else {
    free_f(ptr);
  }
}
void init_hook(void) {
  if (!malloc_f) {
    malloc_f = dlsym(RTLD_NEXT, "malloc");
  }
  if (!free_f) {
    free_f = dlsym(RTLD_NEXT, "free");
  }
}
int main(void) {
    init_hook();
    void *p1 = malloc(8);
    void *p2 = malloc(16);
    void *p3 = malloc(32);
    free(p1);
    free(p2);
    return 0;
}

编译执行:

表示在memleak.c 文件的 main 函数中, 第149行出现内存泄漏问题。

源文件 memleak.c

#define _GNU_SOURCE
#include <dlfcn.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <link.h>
// 方式一:宏定义
#if 0
void *_malloc(size_t size, char *filename,int line) {
    void *ptr = malloc(size);
    char file[128] = {0};
    sprintf(file ,"./mem/%p.mem" ,ptr);
    FILE *fp = fopen(file ,"w");//w小写
    fprintf(fp, "[+]addr: %p filename: %s line: %d\n",ptr,filename,line);
    fflush(fp);
    fclose(fp);
    return ptr;
}
void _free(void *ptr, char *filename,int line) {
    char file[128] = {0};
    sprintf(file,"./mem/%p.mem",ptr);
    if(unlink(file) < 0){//unlink用于在文件系统中删除指定的文件
        printf("double free %p\n",ptr);
        return;
    }
    return free(ptr);
}
// __FILE__ 获取文件名
// __LINE__ 获取函数执行的行号
#define malloc(size)   _malloc(size, __FILE__,__LINE__)
#define free(ptr)      _free(ptr, __FILE__,__LINE__)
//方式二:hook
#elif 1
// gcc -o memleak memleak.c -g -ldl
// addr2line -f -e ./memleak -a 0x400b38
typedef void *(*malloc_t)(size_t size);
malloc_t malloc_f = NULL;
typedef void (*free_t)(void *ptr);
free_t free_f = NULL;
int enable_malloc_hook = 1;
int enable_free_hook = 1;
void *COnvertToELF(void *addr) {
  Dl_info info;
  struct link_map *link;
  dladdr1(addr, &info, (void**)&link,RTLD_DL_LINKMAP);
  return (void*)((size_t)addr - link->l_addr);
}
void *malloc(size_t size) {
  void *ptr = NULL;
  if (enable_malloc_hook) {
    enable_malloc_hook = 0;
    ptr = malloc_f(size);
  // main --> f1() --> f2() --> f3() { __builtin_return_address(0)  }
    void *caller = __builtin_return_address(0);
    char filename[128] = {0};
    sprintf(filename, "./mem/%p.mem", ptr);
    FILE *fp = fopen(filename, "w");
    fprintf(fp, "[+] caller: %p, addr: %p, size: %ld\n",
       COnvertToELF(caller), ptr, size);
    fflush(fp);
    enable_malloc_hook = 1;
  } else {
    ptr = malloc_f(size);
  }
  return ptr;
}
void free(void *ptr) {
  if (enable_free_hook) {
    enable_free_hook = 0;
        char file[128] = {0};
    sprintf(file, "./mem/%p.mem", ptr);
    if (unlink(file) < 0) { // filename no exist;
      printf("double free: %p\n", ptr);
      return ;
    }
    free_f(ptr);
    enable_free_hook = 1;
  } else {
    free_f(ptr);
  }
}
void init_hook(void) {
  if (!malloc_f) {
    malloc_f = dlsym(RTLD_NEXT, "malloc");
  }
  if (!free_f) {
    free_f = dlsym(RTLD_NEXT, "free");
  }
}
#endif
#if 1
int main(void) {
    init_hook();
    void *p1 = malloc(8);
    void *p2 = malloc(16);
    void *p3 = malloc(32);
    free(p1);
    free(p2);
    return 0;
}
#endif

注意:提前在程序目录下创建mem文件夹,编译时添加 -g -ldl

具体使用时只需将该文件的main函数注释掉,与需要检测的程序源文件一起编译执行即可。

目录
相关文章
|
3月前
|
缓存 监控 Python
在Python中,如何检测和处理内存泄漏?
【2月更文挑战第7天】【2月更文挑战第18篇】在Python中,如何检测和处理内存泄漏?
|
4月前
|
安全 Linux 编译器
内存泄漏检测组件的分析与实现(linux c)-mtrace工具使用
内存泄漏产生原因 在堆上使用malloc/remalloc/calloc分配了内存空间,但是没有使用free释放对应的空间。
76 0
|
4月前
|
Java C++
动手实现内存泄漏检测组件
动手实现内存泄漏检测组件
37 1
|
4月前
使用mtrace进行内存泄漏检测
使用mtrace进行内存泄漏检测
76 1
|
2月前
|
IDE Linux 开发工具
内存泄漏检测工具Valgrind:C++代码问题检测的利器(一)
内存泄漏检测工具Valgrind:C++代码问题检测的利器
95 0
|
2月前
|
缓存 Linux iOS开发
【C/C++ 集成内存调试、内存泄漏检测和性能分析的工具 Valgrind 】Linux 下 Valgrind 工具的全面使用指南
【C/C++ 集成内存调试、内存泄漏检测和性能分析的工具 Valgrind 】Linux 下 Valgrind 工具的全面使用指南
68 1
|
2月前
|
缓存 测试技术 开发工具
内存泄漏检测工具Valgrind:C++代码问题检测的利器(二)
内存泄漏检测工具Valgrind:C++代码问题检测的利器
35 0
|
2月前
|
Python
在Python中,如何检测和修复内存泄漏?
在Python中,如何检测和修复内存泄漏?
108 0
|
4月前
|
Web App开发 前端开发 JavaScript
JavaScript 内存泄漏的检测与防范:让你的程序更稳定
JavaScript 内存泄漏的检测与防范:让你的程序更稳定
JavaScript 内存泄漏的检测与防范:让你的程序更稳定
|
4月前
|
缓存 算法 Linux
Linux 内存泄漏检测的基本原理
Linux 内存泄漏检测的基本原理
112 0