在Linux / GCC / C ++中,每当调用malloc / free / new / delete时,我都想logging一些stderr。 我想了解一个库的内存分配,所以我想在运行unit testing的时候生成这个输出。 我使用valgrind进行mem泄漏检测,但是我找不到一个让它只logging分配的选项。
有任何想法吗? 我正在寻找最简单的解决scheme。 重新编译库不是一个选项。
malloc_hook(3)
允许你全局介入你自己的malloc
函数。 (还有__realloc_hook
__free_hook
等等,为了简单起见,我只是把它们留下了。
#include <stdio.h> #include <malloc.h> static void *(*old_malloc_hook)(size_t, const void *); static void *new_malloc_hook(size_t size, const void *caller) { void *mem; __malloc_hook = old_malloc_hook; mem = malloc(size); fprintf(stderr, "%p: malloc(%zu) = %p\n", caller, size, mem); __malloc_hook = new_malloc_hook; return mem; } static void init_my_hooks(void) { old_malloc_hook = __malloc_hook; __malloc_hook = new_malloc_hook; } void (*__malloc_initialize_hook)(void) = init_my_hooks;
$ cat> mem.c <<'EOF' (上面的代码) EOF $ cc -fPIC -shared -o mem.so mem.c $ LD_PRELOAD =。/ mem.so ls 0x7ffc14931adc:malloc(5)= 0xb40010 0x7ffc1492c6b0:malloc(120)= 0xb40030 0x7ffc1497f61a:malloc(12)= 0xb40010 0x7ffc1492be38:malloc(776)= 0xb400b0 ...
printf
可能会调用malloc
,这就是为什么我们暂时撤销钩子。 如果以任何方式勾选malloc
,请注意这一点。
你可以用ltrace跟踪对malloc / free的调用:
#include <stdlib.h> int main (void) { void *ptr = malloc(10); free(ptr); return 0; } $ g++ test.cpp -o test $ ltrace -e malloc,free ./test malloc(10) = 0x804a008 free(0x804a008) = <void> +++ exited (status 0) +++
要追踪新的/删除调用,而不重新编译,你可能需要使用类似LD_PRELOAD来覆盖你自己版本的调用,这正是LeakTracer所做的,可以做你想做的。
这篇文章 (向下滚动到底部)提供了一个非常简洁明了的描述,说明如何覆盖C ++中全局的new
和delete
操作符(注意它没有提供new[]
的例子,但是它在概念上是相似的)。
至于重载malloc和免费的,因为你正在使用Linux和GCC,最简单的方法是使用malloc_hook
和free_hook
。 下面是对这些功能如何工作的很好的描述。
我自己没有测试过这个,但是我确定这些都可以工作:
既然你不想重新编译库,给予有意义的输出(而不是只是“新的23个字节”)可能需要获取堆栈跟踪。 我记得使用函数来导航堆栈,但我现在找不到它们。 也许调用system()和pstack(1)可以做到这一点。
你可以重新定义operator new和delete,并把这个新的定义放在std c ++库之前。 这可能不会捕获相关库所使用的容器和标准组件的调用。 这将需要重新链接。
使用可以使用LD_PRELOAD来动态改变运算符new和delete。 如果您的应用程序是动态链接的,则不需要重新链接。
希望这些指针帮助,我很抱歉,我没有一个配方。