GLIBC:调试内存泄漏:如何解释mtrace()的输出

时间:2020-03-06 14:56:02  来源:igfitidea点击:

我正在尝试调试内存泄漏问题。我正在使用mtrace()获得malloc / free / realloc跟踪。我跑了我的编,现在有一个巨大的日志文件。到目前为止,一切都很好。但是我在解释文件时遇到了问题。看一下这些行:

@ /usr/java/ibm-java2-x86_64-50/jre/bin/libj9prt23.so:[0x2b270a384a34] + 0x1502570 0x68
@ /usr/java/ibm-java2-x86_64-50/jre/bin/libj9prt23.so:[0x2b270a384a34] + 0x1502620 0x30
@ /usr/java/ibm-java2-x86_64-50/jre/bin/libj9prt23.so:[0x2b270a384a34] + 0x2aaab43a1700 0xa80
@ /usr/java/ibm-java2-x86_64-50/jre/bin/libj9prt23.so:[0x2b270a384a34] + 0x1501460 0xa64

奇怪的是,一个呼叫(相同的返回地址)负责4个分配。

甚至陌生人:

@ /usr/java/ibm-java2-x86_64-50/jre/bin/libj9prt23.so:[0x2b270a384a34] + 0x2aaab43a1700 0xa2c
…
@ /usr/java/ibm-java2-x86_64-50/jre/bin/libj9prt23.so:[0x2b270a384a34] + 0x2aaab43a1700 0xa80

在这两行之间,永远不会释放块0x2aaab43a1700。

有人知道如何解释吗?一个电话怎么会导致4个分配?以及malloc如何返回先前已分配的地址?

编辑2008/09/30:
分析GLIBC(mtrace.pl)提供的mtrace()输出的脚本在这里没有任何帮助。它只会说:Alloc 0x2aaab43a1700复制。但是,这怎么可能呢?

解决方案

一种可能的解释是,同一函数分配不同的缓冲区大小吗?这样的例子之一就是strdup。

对于第二个问题,运行时可能会分配一些"静态"暂存区,该暂存区在进程终止之前是不希望释放的。到那时,无论如何,操作系统将在清理之后进行清理。

这样考虑:在Java中,没有析构函数,也不能保证对任何对象都将调用终结方法。

尝试在valgrind下运行应用程序。它可以使我们更好地了解实际泄漏的内容。

我们正在看mtrace的直接输出,这是非常令人困惑和违反直觉的。幸运的是,有一个perl脚本(称为gtrace,在glibc-utils中找到),可以非常轻松地帮助解析此输出。

编译并调试,然后运行mtrace,如下所示:

$ gcc -g -o test test.c
$ MALLOC_TRACE=mtrace.out ./test
$ mtrace test mtrace.out

Memory not freed:
-----------------
   Address     Size     Caller
0x094d9378    0x400  at test.c:6

输出应该更容易消化。

分配内存的函数被多次调用。调用者地址指向进行分配的代码,并且该代码仅运行了不止一次。

这是C语言中的一个示例:

void *allocate (void)
{
  return (malloc(1000));
}

int main()
{
  mtrace();
  allocate();
  allocate();
}

mtrace的输出是:

Memory not freed:
-----------------
           Address     Size     Caller
0x0000000000601460    0x3e8  at 0x4004f6
0x0000000000601850    0x3e8  at 0x4004f6

请注意,呼叫者地址如何相同?这就是mtrace分析脚本说它们相同的原因,因为同一错误被查看一次以上,从而导致多次内存泄漏。

如果可以,使用调试标志(-g)进行编译将很有帮助:

Memory not freed:
-----------------
           Address     Size     Caller
0x0000000000601460    0x3e8  at /home/andrjohn/development/playground/test.c:6
0x0000000000601850    0x3e8  at /home/andrjohn/development/playground/test.c:6