检查 gdb 中的 C/C++ 堆内存统计信息

Posted

技术标签:

【中文标题】检查 gdb 中的 C/C++ 堆内存统计信息【英文标题】:Examining C/C++ Heap memory statistics in gdb 【发布时间】:2011-02-03 14:50:43 【问题描述】:

我正在尝试从 Linux amd64 上的 gdb 中调查 C/C++ 堆的状态,有什么好的方法吗?

我尝试过的一种方法是“调用 mallinfo()”,但不幸的是我无法提取我想要的值,因为 gdb 没有正确处理返回值。

我不容易为我所附加的进程编写一个要编译成二进制文件的函数,所以我可以简单地实现我自己的函数来通过在我自己的代码中调用 mallinfo() 来提取值.是否有一个聪明的技巧可以让我即时执行此操作?

另一种选择可能是定位堆并遍历 malloc 标头/空闲列表;我会很感激任何关于我可以从哪里开始找到这些位置和布局的指针。

我一直在尝试使用 Google 并围绕这个问题阅读了大约 2 个小时,我学到了一些有趣的东西,但仍然没有找到我需要的东西。

【问题讨论】:

你需要了解什么状态?您需要了解哪些统计数据? 堆大小、使用量和空闲量是一个好的开始 gdb 什么地方做得不好? 好吧,我只是根据我的要求正确使用我自己的定义,即能够取消引用“call mallinfo()”返回的结构并查看成员的值其中。 遗憾的是,我认为情况变得更加复杂,因为劣质没有包含 malloc.h 并且“struct mallinfo”似乎不在类型列表中;也许如果是,那么 gdb 将允许我查询其成员。相反,我只返回一个整数值(可能是因为未包含函数定义并且它默认为 int 返回类型);这可能是一个指针,但我不知道如何取消引用它(不是指向内存的指针)。 【参考方案1】:

@fd - RedHat bug 有你的答案。

mallinfo 函数已被弃用,不会更新。真正的查询统计 API 是 TDB。今天,你有malloc_statsmalloc_info。我找不到任何一个文档,但这是他们给你的。

这是否足够接近您的需求?

(gdb) call malloc_stats()
Arena 0:
system bytes     =     135168
in use bytes     =         96
Total (incl. mmap):
system bytes     =     135168
in use bytes     =         96
max mmap regions =          0
max mmap bytes   =          0

(gdb) call malloc_info(0, stdout)
<malloc version="1">
<heap nr="0">
<sizes>
<unsorted from="1228788" to="1229476" total="3917678" count="3221220448"/>
</sizes>
<total type="fast" count="0" size="0"/>
<total type="rest" count="3221220448" size="3917678"/>
<system type="current" size="135168"/>
<system type="max" size="135168"/>
<aspace type="total" size="135168"/>
<aspace type="mprotect" size="135168"/>
</heap>
<total type="fast" count="0" size="0"/>
<total type="rest" count="3221220448" size="3917678"/>
<system type="current" size="135168
/>
<system type="max" size="135168
/>
<aspace type="total" size="135168"/>
<aspace type="mprotect" size="135168"/>
</malloc>

【讨论】:

干得好,我昨晚发现了 malloc_stats() 并在今天早些时候的测试中使用它,效果非常好。我还遇到了 sourceware 的 glibc wiki,它指向 Ulrich Drepper 的 livejournal 与这篇文章 - udrepper.livejournal.com/20948.html - 从 09 年 4 月开始,描述了 mallinfo 的替换(以及其他内容),但我还没有尝试过。感谢您发布输出,看起来很有趣。 +1 顺便问一下,你找到 malloc_info() 的文档了吗?第一个参数是否描述了竞技场编号?我在输出中看到 ,并且在我的测试中 malloc_stats() 显示了许多领域的统计信息(此外: mallinfo() 似乎也受到限制,因为它只显示来自零的信息- th arena,这就是为什么我对它的测试与我看到的 top 报告的内存使用不匹配;此外,没有一个单独的 arena 统计数据增长到足以击中我之前引用的错误)。 我找不到 malloc_info() 的文档。根据消息来源,if (options != 0) return EINVAL - sourceware.org/git/?p=glibc.git;a=blob;f=malloc/…。看起来它遍历了所有领域。 我正在运行的进程标准输出被重定向到某个日志文件。所以call malloc_stats() 没有在控制台上打印出来,而是在那个日志文件上打印出来。我花了将近一个小时才弄明白。【参考方案2】:

如果可以改代码:

#include <malloc.h>
#include <stdio.h>

void dumpMallinfo(void) 
  struct mallinfo m = mallinfo();
  printf("uordblks = %d\nfordblks = %d\n", m.uordblks, m.fordblks);

在GDB中,你可以call dumpMallinfo()

【讨论】:

正如我在问题中所说,我不能,但是这是一种有用的技术。 +1(这是 2 小时谷歌搜索所揭示的方法之一) 找到了一些关于 mallinfo() 的有用信息;它似乎没有准备好 64 位。返回的结构由 int 成员组成,不处理大于 4GB 的字节大小。尽管我发现 Debian 和 RedHat 错误报告都以 NOTABUG/WONTFIX 的形式关闭,但我还没有找到任何解决此问题的证据。 在下面重申我对 dave 其他答案的评论: mallinfo() 似乎也受到限制,因为它只显示来自第零场的信息,这就是我对它的测试不匹配的原因我看到的 top 报告的内存使用情况;此外,没有一个单一的竞技场统计数据增长到足以解决我之前提到的错误。 malloc_stats() 显示来自所有领域的信息。

以上是关于检查 gdb 中的 C/C++ 堆内存统计信息的主要内容,如果未能解决你的问题,请参考以下文章

debug套路

七:JVM调优工具详解及调优实战

如何以编程方式获取堆栈内存统计信息?

gdb 搜索核心转储内存

错误:线程“守护程序运行状况统计”中的异常 java.lang.OutOfMemoryError:Java 堆空间

NVIDIA Nsight Systems CLI 未获取内存统计信息