在Linux/GCC/C++中,每次调用malloc/free/new/delete时,我都会记录stderr的内容。我试图理解一个库的内存分配,所以我想在运行单元测试时生成这个输出。我使用valgrind进行mem泄漏检测,但是我找不到一个让它只记录分配的选项。每当调用malloc/free时输出到stderr
任何想法?我正在寻找最简单的解决方案。重新编译库不是一个选项。
在Linux/GCC/C++中,每次调用malloc/free/new/delete时,我都会记录stderr的内容。我试图理解一个库的内存分配,所以我想在运行单元测试时生成这个输出。我使用valgrind进行mem泄漏检测,但是我找不到一个让它只记录分配的选项。每当调用malloc/free时输出到stderr
任何想法?我正在寻找最简单的解决方案。重新编译库不是一个选项。
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' (the code above) 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
,请注意这一点。
This article(向下滚动至底部)提供了如何覆盖全局new
和delete
运营商在C非常清晰和简洁的描述++(请注意,它不会为new[]
提供一个例子,但它在概念上类似于) 。
就覆盖malloc和free而言,由于您正在Linux和GCC上工作,最简单的方法是使用malloc_hook
和free_hook
。 Here是对这些功能如何工作的非常好的描述。
我没有这个测试自己,但我敢肯定这会工作:
既然你不想重新编译库,让有意义的输出(相对于只是“新要求23字节“)可能需要获取堆栈跟踪。我记得使用函数来导航堆栈,但我现在找不到它们。也许对system()和pstack(1)的调用可以做到这一点。
您可以重新定义运算符new和delete,并将此新定义放在std C++库之前。这可能无法捕获相关库正在使用的容器和标准组件的调用。这需要重新链接。
使用可以使用LD_PRELOAD来更改运算符new和delete动态。如果您的应用程序是动态链接的,则不需要重新链接。
希望这些指针帮助,我很抱歉,我没有食谱。
您可以跟踪到的malloc /电话免费与ltrace:
#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做什么,可能会做你想做的。
这两种解决方案似乎都需要重新编译相关库。 – 2008-11-15 14:56:52