当前位置:  开发笔记 > 编程语言 > 正文

为malloc创建一个包装函数,在C中创建free

如何解决《为malloc创建一个包装函数,在C中创建free》经验,为你挑选了5个好方法。

我试图创建一个包装函数free,并malloc用C来帮助通知我的内存泄漏.有谁知道什么时候我打电话怎么这么声明这些功能malloc()free()它会调用我的自定义功能,而不是标准的lib功能?



1> Alex B..:

你有几个选择:

    GLIBC特定的解决方案(主要是Linux).如果你的编译环境是glibcgcc,首选方法是使用malloc的钩子.它不仅可以让你指定自定义mallocfree,同时也将通过堆栈上的返回地址识别呼叫方.

    POSIX特定的解决方案.定义mallocfree作为可执行文件中原始分配例程的包装,它将"覆盖"libc中的版本.包装里面,你可以调用到原来的malloc实现,你可以看一下使用dlsymRTLD_NEXT处理.定义包装函数的应用程序或库需要链接-ldl.

    #define _GNU_SOURCE
    #include 
    #include 
    
    void* malloc(size_t sz)
    {
        void *(*libc_malloc)(size_t) = dlsym(RTLD_NEXT, "malloc");
        printf("malloc\n");
        return libc_malloc(sz);
    }
    
    void free(void *p)
    {
        void (*libc_free)(void*) = dlsym(RTLD_NEXT, "free");
        printf("free\n");
        libc_free(p);
    }
    
    int main()
    {
        free(malloc(10));
        return 0;
    }
    

    特定于Linux.您可以通过在LD_PRELOAD环境变量中指定动态库来非侵入地覆盖动态库中的函数.

    LD_PRELOAD=mymalloc.so ./exe
    

    Mac OSX具体.

    与Linux相同,除了您将使用DYLD_INSERT_LIBRARIES环境变量.


您正在自定义malloc中使用printf(),但printf()本身使用malloc。我遇到了例如“ LD_PRELOAD =。/ malloc.so ls”的段错误。这不是创建无限递归吗?如何告诉我们的自定义malloc内部的函数使用libc-malloc?

2> Grzegorz Wie..:

您可以使用LD_PRELOAD执行包装和"覆盖"功能 - 与前面所示的示例类似.

LD_PRELOAD=/path.../lib_fake_malloc.so ./app

但我建议这个"稍微"更聪明,我的意思是调用dlsym一次.

#define _GNU_SOURCE
#include 
#include 
#include 

void* malloc(size_t size)
{
    static void* (*real_malloc)(size_t) = NULL;
    if (!real_malloc)
        real_malloc = dlsym(RTLD_NEXT, "malloc");

    void *p = real_malloc(size);
    fprintf(stderr, "malloc(%d) = %p\n", size, p);
    return p;
}

例如我在这里找到的:http://www.jayconrod.com/cgi/view_post.py?23由Jay Conrod发布.

但是我在这个页面上发现非常酷的是:GNU链接器提供了一个有用的选项--wrap.当我检查"man ld"时,有以下示例:

void *
__wrap_malloc (size_t c)
{
    printf ("malloc called with %zu\n", c);
    return __real_malloc (c);
}

我同意他们的"琐碎的例子":).甚至不需要dlsym.

让我,我引用我的"man ld"页面的另一部分:

--wrap=symbol
       Use a wrapper function for symbol.
       Any undefined reference to symbol will be resolved to "__wrap_symbol".
       Any undefined reference to "__real_symbol" will be resolved to symbol.

我希望,描述完整,并展示如何使用这些东西.



3> user9869932..:

很抱歉重新开放7岁的职位。

就我而言,我需要将memalign / aligned_malloc包装在malloc下。在尝试了其他解决方案之后,我最终实现了下面列出的解决方案。它似乎工作正常。

mymalloc.c。

/* 
 * Link-time interposition of malloc and free using the static
 * linker's (ld) "--wrap symbol" flag.
 * 
 * Compile the executable using "-Wl,--wrap,malloc -Wl,--wrap,free".
 * This tells the linker to resolve references to malloc as
 * __wrap_malloc, free as __wrap_free, __real_malloc as malloc, and
 * __real_free as free.
 */
#include 

void *__real_malloc(size_t size);
void __real_free(void *ptr);


/* 
 * __wrap_malloc - malloc wrapper function 
 */
void *__wrap_malloc(size_t size)
{
    void *ptr = __real_malloc(size);
    printf("malloc(%d) = %p\n", size, ptr);
    return ptr;
}

/* 
 * __wrap_free - free wrapper function 
 */
void __wrap_free(void *ptr)
{
    __real_free(ptr);
    printf("free(%p)\n", ptr);
}



4> Raymond Mart..:

在C中,我使用的方法类似于:

#define malloc(x) _my_malloc(x, __FILE__, __LINE__)
#define free(x) _my_free(x)

这使我能够毫不费力地检测分配内存的行和文件.它应该是跨平台的,但如果已经定义了宏,则会遇到问题(如果您使用另一个内存泄漏检测器,则应该是这种情况.)

如果你想在C++中实现相同的,那么这个过程有点复杂,但使用相同的技巧.


@Shahbaz:ISO/IEC 9899:2011,§7.1.3**保留标识符**说: - _所有以下划线开头的标识符以及大写字母或另一个下划线总是保留用于任何用途._ - _所有标识符以下划线开头总是保留用作普通和标签名称空间中具有文件范围的标识符.我认为`_my_malloc()`作为静态函数违反了第二个限制.

5> Walter Brigh..:

这是我多年来使用的一组包装函数(当我浸入C时仍然会这样做)来检测不自由的内存,多次释放内存,引用free'd内存,缓冲区溢出/下溢以及释放内存没有分配.

ftp://ftp.digitalmars.com/ctools.zip

他们已经存在了25年并证明了自己.

您可以使用宏预处理器重新定义malloc并自由使用mem包,但我建议不要使用它,因为它不会将库调用重定向到malloc,就像strdup那样.

推荐阅读
地之南_816
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有