总序
malloc和free操作是c++/c提供给用户管理内存的接口。我们可以通过一些操作,将malloc和free的操作由我们来接管。这有助于我们进行debug,同时也可以基于此,开发自己的内存检测工具。
需要掌握的前置知识:
- malloc和free的原理(optional)
使用GNU自带的hook函数实现操作
需要掌握的前置知识:
- hook(钩子函数)
GNU提供了四个钩子函数,它们分别是:__malloc_hook、__realloc_hook、__free_hook、__memalign_hook
TBC
使用动态链接库的原理实现无侵入的hook操作
需要掌握的前置知识:
- 动态链接库
简而言之,默认情况下,动态链接库的搜寻顺序是LD_PRELOAD --> LD_LIBRARY_PATH --> /lib --> /usr/lib
。malloc
和 free
函数的实现通常位于 C 标准库的动态链接库中,通常位于/lib
或 /usr/lib
目录下。我们可以通过设置LD_PRELOAD
的参数,使得链接器加载别的动态链接库,覆盖正常的函数库。
free函数的实现
#define _GNU_SOURCE //定义宏,RTLD_NEXT依赖此宏
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
void free(void *ptr) {
void(*freep)() = NULL;
freep = dlsym(RTLD_NEXT, "free"); //RTLD_NEXT:不要在此so中寻找此符号,而是按照顺序在下一个so中进行寻找
freep(ptr);
}
malloc函数的实现
#define _GNU_SOURCE
#include <stdio.h>
#include <dlfcn.h>
void* malloc(size_t size) {
void* (*mallocp)(size_t size) = NULL;
mallocp = dlsym(RTLD_NEXT, "malloc");
void * p = mallocp(size);
return p;
}
- 注意malloc原型的返回值和签名
- 注意在malloc中慎用prinrf函数,在某些版本中可能会涉及到malloc,导致循环引用。可以使用char数组代替。
编译与执行
gcc -shared -fpic -o myfree.so myfree.c -ldl //将对应c文件变成为动态库
$ LD_PRELOAD="./myfree.so" ./dfree //链接动态库并启动程序