mallochook内存分配回调(glibc-3-内存)

概述:glibc提供的mallochook机制是通过重新指定内存管理的回调函数指针来实现自定义的内存管理方式。

1. 原型

       #include <malloc.h>

       void *(*__malloc_hook)(size_t size, const void *caller);

       void *(*__realloc_hook)(void *ptr, size_t size, const void *caller);

       void *(*__memalign_hook)(size_t alignment, size_t size,
                                const void *caller);

       void (*__free_hook)(void *ptr, const void *caller);

       void (*__malloc_initialize_hook)(void);

       void (*__after_morecore_hook)(void);

将这些函数地址指向自定义的函数,在调用对应的malloc等函数的时候,将会被自动调用到自定义的函数。

2. 范例

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <malloc.h>

typedef void *(*malloc_hook_fun_t)(size_t size, const void *caller);
typedef void  (*free_hook_fun_t)(void *ptr, const void *caller);

void replace_hook(void);
void restore_hook(void);

malloc_hook_fun_t old_malloc_hook = NULL;
free_hook_fun_t old_free_hook = NULL;

int replaced = 0;

void *my_malloc_fun(size_t size, const void *caller)
{

        restore_hook();

        void *ret = malloc(size);

        printf("+%p:[%p]\n", caller - 1, ret);

        replace_hook();


        return ret;
}

void my_free_fun(void *ptr, const void *caller)
{
        restore_hook();

        printf("-%p:[%p]\n", caller - 1, ptr);

        free(ptr);

        replace_hook();
}

void replace_hook(void)
{
        assert(!replaced);
        replaced = 1;

        old_malloc_hook = __malloc_hook;
        old_free_hook = __free_hook;

        __malloc_hook = my_malloc_fun;
        __free_hook = my_free_fun;

}

void restore_hook(void)
{
        assert(replaced);
        replaced = 0;
        __malloc_hook = old_malloc_hook;
        __free_hook = old_free_hook;
}

int main(int argc, char **argv)
{
        replace_hook();

        char *p = malloc(100);

        free(p);

        restore_hook();

        return 0;
}
  1. 定义old_malloc_hookold_free_hook用来保存库自带的内存分配函数。当进行实际内存管理时,恢复回来进行实际的内存分配和释放;
  2. 定义replace_hookrestore_hook函数,方便进行回调函数的替换和恢复;
  3. 定义my_malloc_funmy_free_fun来替换自带的内存分配、释放函数,用于自定义的内存记录、追踪。

3. 编译

$ gcc malloc_hook.c -g

  1. 编译会有告警,告警信息是:不建议使用这些回调函数。对于单线程使用替换回调,是一种可行的方式,对于多线程的话,就会导致竞争,不适合使用回调函数。如果说是要进行内存泄漏扫描,可以考虑使用一个叫做valgrind的工具。
  2. 使用-g参数是为了后续将输出的转换为代码行号。

4. 运行结果

  1. 执行结果
$ ./a.out
+0x400808:[0x1c19010]
-0x400818:[0x1c19010]
  1. 地址转换结果
$ addr2line -f -e a.out -a 0x400808
0x0000000000400808
main
/home/centos/gnuc/c3/jianshu_malloc_hook.c:68

$ addr2line -f -e a.out -a 0x400818
0x0000000000400818
main
/home/centos/gnuc/c3/jianshu_malloc_hook.c:70

通过执行输出打印的调用地址,然后将地址转换层代码位置,这就和之前的 mtrace 的功能类似了。

5. 结论

  1. malloc_hook回调机制适用于单线程,可以通过重新定义内存处理函数来进行内存的记录、追踪和管理等功能。
  2. 对于多线程,malloc_hook机制会出现竞争,不建议使用。如果是调试阶段,可以考虑使用valgrind来进行内存追踪。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容