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

发布于 2024-07-06 02:12:17 字数 1135 浏览 9 评论 0原文

我正在尝试调试内存泄漏问题。 我正在使用 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() 输出的脚本在这里没有任何帮助。 它只会说:分配 0x2aaab43a1700 重复。 但这怎么可能发生呢?

I’m trying to debug a memory leak problem. I’m using mtrace() to get a malloc/free/realloc trace. I’ve ran my prog and have now a huge log file. So far so good. But I have problems interpreting the file. Look at these lines:

@ /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

The strange about this is that one call (same return address) is responsible for 4 allocations.

Even stranger:

@ /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

Between those two lines the block 0x2aaab43a1700 is never being freed.

Does anyone know how to explain this? How could one call result in 4 allocations? And how could malloc return an address which was already allocated previously?

edit 2008/09/30:
The script to analyze the mtrace() output provided by GLIBC (mtrace.pl) isn't of any help here. It will just say: Alloc 0x2aaab43a1700 duplicate. But how could this happen?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

假装爱人 2024-07-13 02:12:17

您正在查看 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

输出应该更容易理解。

You're looking at the direct output of mtrace, which is extremely confusing and counterintuitive. Luckily, there is a perl script (called mtrace, found within glibc-utils) which can very easily help the parsing of this output.

Compile your build with debugging on, and run mtrace like such:

$ 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

The output should be a lot easier to digest.

公布 2024-07-13 02:12:17

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

下面是一个 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

The function that is allocating the memory is being called more than once. The caller address points to the code that did the allocation, and that code is simply being run more than once.

Here is an example in C:

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

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

The output from mtrace is:

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

Note how the caller address is identical? This is why the mtrace analysing script is saying they are identical, because the same bug is being seen more that once, resulting in several memory leaks.

Compiling with debugs flags (-g) is helpful if you can:

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
够钟 2024-07-13 02:12:17

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

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

这样想:在 Java 中,没有析构函数,并且不能保证任何对象都会调用终结。

One possible explanation is that the same function is allocating different buffer sizes? One such example is strdup.

For the second question, it is possible that the runtime is allocating some "static" scratch area which is not intended to be freed until the process is terminated. And at that point, the OS will clean-up after the process anyway.

Think about it this way: in Java, there are no destructors, and no guarantees that finalization will be ever called for any object.

孤蝉 2024-07-13 02:12:17

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

Try running your app under valgrind. It might give you a better view about what is actually being leaked.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文