- #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方法来重定向 malloc 和 free 函数, 与此同时通过__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函数注释掉,与需要检测的程序源文件一起编译执行即可。