美文网首页GNU C LIB
mallochook内存分配回调(glibc-3-内存)

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

作者: YBHello | 来源:发表于2018-04-29 08:38 被阅读0次

    概述: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来进行内存追踪。

    相关文章

      网友评论

        本文标题:mallochook内存分配回调(glibc-3-内存)

        本文链接:https://www.haomeiwen.com/subject/qjkolftx.html