> 文章列表 > malloc hook进行内存泄漏检测

malloc hook进行内存泄漏检测

malloc hook进行内存泄漏检测

记录下使用malloc的hook形式,写个小的demo,并记录遇到的问题

1. 实现代码

   CMakeLists.txt和相应的memory_leak.cpp文件

cmake_minimum_required(VERSION 3.14)
project(demo)set(_SRCmemory_leak.cpp)add_library(memory_leak SHARED ${_SRC})
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <execinfo.h>//实际内存申请的函数
extern void *__libc_malloc(size_t size);
int enable_malloc_hook = 1;extern void __libc_free(void* p);
int enable_free_hook = 1;void *malloc(size_t size) 
{if (enable_malloc_hook) {enable_malloc_hook = 0;void *p = __libc_malloc(size); //重载达到劫持后 实际内存申请// void *caller = __builtin_return_address(0); // 0// char buff[128] = {0};// sprintf(buff, "./mem/%p.mem", p);// FILE *fp = fopen(buff, "w");// // fprintf(fp, "[+%p] --> addr:%p, size:%ld\\n", caller, p, size);// void* trace[16];// char** messages = (char**)NULL;// int i, trace_size = 0;// trace_size  = backtrace(trace, 16);// messages    = backtrace_symbols(trace, trace_size);// for (i=0; i<trace_size; ++i) // {//     fprintf(fp, "[bt][%s]\\n", messages[i]);// }// fflush(fp);fclose(fp); //freeprintf("=====Malloc: %p\\n", p);enable_malloc_hook = 1;return p;} else {return __libc_malloc(size);}return NULL;
}void free(void *p) 
{if (NULL == p)   // 这里加这个判断是因为backtrace函数的调用不知道为什么会调用free并传递的是0x0指针{return;}if (enable_free_hook) {printf("=====free: %p\\n", p);enable_free_hook = 0;char buff[128] = {0};sprintf(buff, "./mem/%p.mem", p);if (unlink(buff) < 0) { // no existprintf("double free: %p\\n", p);}__libc_free(p);// rm -rf p.memenable_free_hook = 1;} else {__libc_free(p);}
}

测试函数:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <thread>
#include <chrono>
int main()
{// while (true){std::this_thread::sleep_for(std::chrono::milliseconds(500));void * ptr1 = malloc(10);}return 0;
}

使用方式:

        export LD_PRELOAD=./libmemory_leak.so

        ./demo

2. 遇到问题

  •  为什么memory_leak使用cpp后续,直接执行demo就直接死机

        Segmentation fault (core dumped)

        但是使用.c后缀编译就没问题

        原因:

                应该和CPP的签名有关系,直接在使用memory_leak.cpp编译,并使用

        extern "C"

        {

                //所有代码

        }

        使用OK

  • 上面代码直接运行是可以的,但是为什么gdb的时候会出现死机,感觉是在递归调用,但是逻辑中已经添加了递归的限制,会反复输出二次释放的信息

        直接将memory_leak.cpp的源码直接嵌套在main.cpp中,就可以gdb了,为什么?

        实际使用中应该就使使用独立的动态库然后LD_PRELOAD的方式进行的呀

        

  • 想要直接gdb ./demo | tee log.txt,通过log.txt查看究竟是否真的二次释放了

 可以看到第一个free之前都没有调用malloc,为什么没有调用malloc就调用了free呢?

 猜测:难道除了系统了free还有别的资源free函数被覆盖了,但是这个资源却不是通过malloc申请的?