每当调用malloc/free时输出到stderr

4
使用Linux/GCC/C++,我想在调用malloc/free/new/delete时记录一些内容到stderr。我正在尝试了解一个库的内存分配情况,因此我想在运行单元测试时生成这个输出。我使用valgrind进行内存泄漏检测,但我找不到一个选项来使它只记录分配情况。
有什么想法吗?我正在寻找最简单的可能解决方案。重新编译库不是一个选项。
4个回答

15

您可以使用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) +++

如果想要在不重新编译代码的情况下跟踪new/delete调用,您可能需要使用类似于LD_PRELOAD的东西来覆盖调用并使用您自己的版本。这正是LeakTracer所做的,这可能是您想要的。


5

这篇文章(向下滚动到底部)提供了非常清晰简洁的说明,介绍了如何在C++中覆盖全局newdelete操作符(请注意,它没有为new[]提供示例,但概念类似)。

至于覆盖malloc和free,由于您正在Linux上使用GCC,最简单的方法是使用malloc_hookfree_hook这里有一个非常好的描述,介绍了这些函数的工作原理。


这两种解决方案似乎都需要重新编译相关的库。 - Robert Gamble

4

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,请小心。


1

我自己没有测试过,但我相信这些方法会起作用:

  • 由于您不想重新编译库,因此提供有意义的输出(而不仅仅是“为23个字节调用了new”)可能需要获取堆栈跟踪。我记得使用函数来导航堆栈,但现在找不到它们了。也许调用system()和pstack(1)可以解决问题。

  • 您可以重新定义operator new和delete,并将此新定义放在std c++库之前。这可能无法捕获所涉及的库正在使用的容器和标准组件的调用。这将需要重新链接。

  • 使用LD_PRELOAD动态更改operator new和delete。如果您的应用程序是动态链接的,则不需要重新链接。

希望这些指针能够帮助您,很抱歉我没有具体的解决方案。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接