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

嗨,我试图创build免费的包装函数和C中的malloc来帮助通知我的内存泄漏。 有没有人知道如何声明这些函数,所以当我调用malloc()和free()它会调用我的自定义函数,而不是标准的lib函数?

你有几个select:

  1. GLIBC特定的解决scheme(主要是Linux)。 如果你的编译环境是gcc glibc ,首选的方法是使用malloc钩子 。 它不仅可以让你指定自定义的mallocfree ,还可以通过堆栈上的返回地址来标识调用者。

  2. POSIX特定的解决scheme。 定义malloc并将其作为可执行文件的原始分配例程free ,这将从libc中“覆盖”版本。 在包装内部,你可以调用原始的malloc实现,你可以使用dlsymRTLD_NEXT句柄来查找。 定义包装函数的应用程序或库需要链接-ldl

     #define _GNU_SOURCE #include <dlfcn.h> #include <stdio.h> 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; } 
  3. 特定的Linux。 您可以通过在LD_PRELOAD环境variables中指定dynamic库来非侵入性地覆盖函数。

     LD_PRELOAD=mymalloc.so ./exe 
  4. Mac OSX特定。

    与Linux相同,只是您将使用DYLD_INSERT_LIBRARIES环境variables。

您可以使用LD_PRELOAD来执行封装和“覆盖”function – 与前面的示例类似。

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

但我build议做这个“稍微”更聪明,我的意思是调用dlsym一次

 #define _GNU_SOURCE #include <stdio.h> #include <stdint.h> #include <dlfcn.h> 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; } 

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

但是我在这个页面上发现的非常酷: 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. 

我希望,描述是完整的,并显示如何使用这些东西。

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

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

这使我能够在没有太多困难的情况下检测到分配内存的行和文件。 它应该是跨平台的,但是如果已经定义了macros,就会遇到问题(只有在使用另一个内存泄漏检测器的情况下才会出现这种情况)。

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

下面是一些我用了多年的包装函数(当我进入C时仍然会这样做)来检测自由内存,多次释放内存,释放内存的引用,缓冲区溢出/下溢以及释放内存没有分配。

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

他们已经有25年的历史了,并且已经certificate了自己。

您可以使用macros预处理器来重新定义malloc并免费使用mem包,但我build议不要这样做,因为它不会像strdup那样将库调用redirect到malloc。

如果你的目标是消除内存泄漏,一个更简单,不那么干扰的方法是使用Valgrind (免费)或Purify (昂贵)的工具。

如果为malloc()和free()定义自己的函数,并将其与您的应用程序明确链接,则应优先使用函数来优先于库中的函数。

然而,你的叫做“malloc”的函数不能调用库的malloc函数,因为在'c'中没有单独的名字空间的概念。 换句话说,你必须实现malloc的内部并释放自己。

另一种方法是编写函数my_malloc()和my_free(),它们调用标准库函数。 这将意味着任何调用malloc的代码将不得不被改变来调用你的my_xxx函数。

对不起,重新开放一个7岁的职位。

在我的情况下,我需要包装malloc下的memalign / aligned_malloc。 在尝试其他解决scheme后,我结束了实施下面列出的一个。 它似乎工作正常。

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 <stdio.h> 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); } 

如果您使用Linux,则可以使用malloc_hook()(使用GNU glibc)。 这个函数允许你在调用实际的malloc之前让malloc调用你的函数。 手册页有一个如何使用它的例子。

如果你只是谈论你所掌握的记忆,也就是说,你自己的malloc和free,你可以看看rmdebug 。 也许这就是你要写的东西,所以你可以节省一些时间。 它有一个非常自由的许可证,如果这对你很重要的话。

我个人使用它在一个项目中,寻找内存泄漏,好处是它比valgrind快得多,但它不是那么强大,所以你没有得到完整的调用堆栈。