5

我正在尝试调试内存泄漏问题。我正在使用mtrace()来获取 malloc/free/realloc 跟踪。我已经运行了我的 prog,现在有一个巨大的日志文件。到现在为止还挺好。但我在解释文件时遇到问题。看看这些行:

@ /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 重复。但这怎么会发生呢?

4

4 回答 4

8

您正在查看 mtrace 的直接输出,这非常令人困惑和违反直觉。幸运的是,有一个 perl 脚本(称为 mtrace,在 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

输出应该容易消化。

于 2008-09-30T18:50:17.670 回答
5

分配内存的函数被多次调用。调用者地址指向执行分配的代码,并且该代码只是运行了多次。

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

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

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

mtrace 的输出是:

内存未释放:
-----------------
           地址大小调用者
0x0000000000601460 0x3e8 在 0x4004f6
0x0000000000601850 0x3e8 在 0x4004f6

注意来电者地址是如何相同的?这就是为什么 mtrace 分析脚本说它们是相同的,因为相同的错误被多次看到,导致多次内存泄漏。

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

内存未释放:
-----------------
           地址大小调用者
0x0000000000601460 0x3e8 在 /home/andrjohn/development/playground/test.c:6
0x0000000000601850 0x3e8 在 /home/andrjohn/development/playground/test.c:6
于 2008-10-03T21:07:33.183 回答
0

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

对于第二个问题,运行时可能正在分配一些“静态”暂存区,这些暂存区在进程终止之前不会被释放。到那时,操作系统无论如何都会在该过程之后进行清理。

可以这样想:在 Java 中,没有析构函数,也无法保证任何对象都会调用终结。

于 2008-09-30T17:04:52.667 回答
0

尝试在 valgrind 下运行您的应用程序。它可能会让您更好地了解实际泄露的内容。

于 2008-09-30T17:10:55.897 回答