内存泄漏检测组件的实现

简介: 内存泄漏检测组件的实现
  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函数注释掉,与需要检测的程序源文件一起编译执行即可。

目录
相关文章
|
6天前
|
C语言 Android开发 C++
基于MTuner软件进行qt的mingw编译程序的内存泄漏检测
本文介绍了使用MTuner软件进行Qt MinGW编译程序的内存泄漏检测的方法,提供了MTuner的下载链接和测试代码示例,并通过将Debug程序拖入MTuner来定位内存泄漏问题。
基于MTuner软件进行qt的mingw编译程序的内存泄漏检测
|
3月前
|
存储 算法 Java
Java面试题:深入探究Java内存模型与垃圾回收机制,解释JVM中堆内存和栈内存的主要区别,谈谈对Java垃圾回收机制的理解,Java中的内存泄漏及其产生原因,如何检测和解决内存泄漏问题
Java面试题:深入探究Java内存模型与垃圾回收机制,解释JVM中堆内存和栈内存的主要区别,谈谈对Java垃圾回收机制的理解,Java中的内存泄漏及其产生原因,如何检测和解决内存泄漏问题
53 0
|
4天前
|
设计模式 Java Android开发
安卓应用开发中的内存泄漏检测与修复
【9月更文挑战第30天】在安卓应用开发过程中,内存泄漏是一个常见而又棘手的问题。它不仅会导致应用运行缓慢,还可能引发应用崩溃,严重影响用户体验。本文将深入探讨如何检测和修复内存泄漏,以提升应用性能和稳定性。我们将通过一个具体的代码示例,展示如何使用Android Studio的Memory Profiler工具来定位内存泄漏,并介绍几种常见的内存泄漏场景及其解决方案。无论你是初学者还是有经验的开发者,这篇文章都将为你提供实用的技巧和方法,帮助你打造更优质的安卓应用。
|
1月前
|
Linux Windows
检测进程内存的活跃程度
检测进程内存的活跃程度
|
2月前
|
Linux 测试技术 C++
内存管理优化:内存泄漏检测与预防。
内存管理优化:内存泄漏检测与预防。
44 2
|
3月前
|
监控 Java Android开发
探究Android应用开发中的内存泄漏检测与修复
在移动应用的开发过程中,优化用户体验和提升性能是至关重要的。对于Android平台而言,内存泄漏是一个常见且棘手的问题,它可能导致应用运行缓慢甚至崩溃。本文将深入探讨如何有效识别和解决内存泄漏问题,通过具体案例分析,揭示内存泄漏的成因,并提出相应的检测工具和方法。我们还将讨论一些最佳实践,帮助开发者预防内存泄漏,确保应用稳定高效地运行。
|
5月前
|
算法 Java Python
【Python 的内存管理机制专栏】Python 内存管理实战:性能优化与内存泄漏检测
【5月更文挑战第18天】Python内存管理关乎程序性能与稳定性。优化包括避免过多临时对象,如优化列表推导式减少对象创建。警惕循环引用造成的内存泄漏,如示例中的Node类。使用`gc`模块检测泄漏,通过`gc.set_debug(gc.DEBUG_LEAK)`和`gc.collect()`获取信息。实践中需持续分析内存使用,优化算法、数据结构和资源释放,以提升程序质量与效率。
63 9
【Python 的内存管理机制专栏】Python 内存管理实战:性能优化与内存泄漏检测
|
4月前
|
Java Linux PHP
【应急响应】后门攻击检测指南&Rookit&内存马&权限维持&WIN&Linux
【应急响应】后门攻击检测指南&Rookit&内存马&权限维持&WIN&Linux
|
4月前
|
监控 Linux 测试技术
edac是检测什么的,和centos内存条损害检测工具
【6月更文挑战第1天】edac是检测什么的,和centos内存条损害检测工具
110 2
|
4月前
|
Java 数据库连接 图形学
JVM内存泄漏检测与处理
JVM内存泄漏检测与处理
26 0

热门文章

最新文章

下一篇
无影云桌面