我试图创建一个包装函数free
,并malloc
用C来帮助通知我的内存泄漏.有谁知道什么时候我打电话怎么这么声明这些功能malloc()
和free()
它会调用我的自定义功能,而不是标准的lib功能?
你有几个选择:
GLIBC特定的解决方案(主要是Linux).如果你的编译环境是glibc
有gcc
,首选方法是使用malloc的钩子.它不仅可以让你指定自定义malloc
和free
,同时也将通过堆栈上的返回地址识别呼叫方.
POSIX特定的解决方案.定义malloc
并free
作为可执行文件中原始分配例程的包装,它将"覆盖"libc中的版本.包装里面,你可以调用到原来的malloc
实现,你可以看一下使用dlsym
与RTLD_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
环境变量.
您可以使用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.
我希望,描述完整,并展示如何使用这些东西.
很抱歉重新开放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. */ #includevoid *__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); }
在C中,我使用的方法类似于:
#define malloc(x) _my_malloc(x, __FILE__, __LINE__) #define free(x) _my_free(x)
这使我能够毫不费力地检测分配内存的行和文件.它应该是跨平台的,但如果已经定义了宏,则会遇到问题(如果您使用另一个内存泄漏检测器,则应该是这种情况.)
如果你想在C++中实现相同的,那么这个过程有点复杂,但使用相同的技巧.
这是我多年来使用的一组包装函数(当我浸入C时仍然会这样做)来检测不自由的内存,多次释放内存,引用free'd内存,缓冲区溢出/下溢以及释放内存没有分配.
ftp://ftp.digitalmars.com/ctools.zip
他们已经存在了25年并证明了自己.
您可以使用宏预处理器重新定义malloc并自由使用mem包,但我建议不要使用它,因为它不会将库调用重定向到malloc,就像strdup那样.