为malloc创build一个包装函数,在C中创build一个free包装函数
嗨,我试图创build免费的包装函数和C中的malloc来帮助通知我的内存泄漏。 有没有人知道如何声明这些函数,所以当我调用malloc()和free()它会调用我的自定义函数,而不是标准的lib函数?
你有几个select:
-
GLIBC特定的解决scheme(主要是Linux)。 如果你的编译环境是
gcc
glibc
,首选的方法是使用malloc钩子 。 它不仅可以让你指定自定义的malloc
和free
,还可以通过堆栈上的返回地址来标识调用者。 -
POSIX特定的解决scheme。 定义
malloc
并将其作为可执行文件的原始分配例程free
,这将从libc中“覆盖”版本。 在包装内部,你可以调用原始的malloc
实现,你可以使用dlsym
和RTLD_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; }
-
特定的Linux。 您可以通过在
LD_PRELOAD
环境variables中指定dynamic库来非侵入性地覆盖函数。LD_PRELOAD=mymalloc.so ./exe
-
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快得多,但它不是那么强大,所以你没有得到完整的调用堆栈。