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

34

我正在尝试在Linux amd64上使用gdb来调查C/C++堆的状态,有没有一种好的方法可以做到这一点?

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

我不能轻松地编写一个函数编译到我所附加的进程的二进制文件中,因此我可以通过调用自己代码中的mallinfo()实现自己的函数来提取值。也许有一个聪明的技巧可以让我即时完成这个操作吗?

另一个选择可能是定位堆并遍历malloc头/空闲列表;我将感激任何指向我能够开始查找这些位置和布局的指针。

我已经尝试了谷歌搜索和阅读相关问题约2小时,学到了一些有趣的东西,但仍然没有找到我需要的内容。


1
你需要了解状态方面的知识吗?你需要了解哪些统计数据呢? - Kaleb Pederson
堆的大小、已使用量和可用量是一个不错的起点。 - Mike Tunnicliffe
GDB没有正常工作的原因是什么? - leedm777
我只是根据我的需求使用自己的“正确”定义,这意味着能够取消引用由“call mallinfo()”返回的结构并查看其中成员的值。 - Mike Tunnicliffe
很遗憾,我认为情况变得更加复杂,因为inferior没有包含malloc.h文件,而“struct mallinfo”似乎不在类型列表中;也许如果它在列表中,gdb就可以允许我查询其成员。相反,我只得到一个整数值返回(可能是因为函数定义未被包含,并且默认为int返回类型);这可能是一个指针,但我不知道如何对其进行解引用(不是指向inferior内存的指针)。 - Mike Tunnicliffe
2个回答

34

@fd - RedHat bug已经给出了你的答案。

mallinfo函数已被弃用,将不再更新。真正的查询统计API尚未确定。目前可以使用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,其中有这篇文章-http://udrepper.livejournal.com/20948.html-来描述mallinfo的替代方案(以及其他事情),但我还没有尝试过。感谢您发布输出,看起来非常有趣。+1 - Mike Tunnicliffe
顺便问一下,你找到malloc_info()的文档了吗?第一个参数是否描述了竞技场编号?我在输出中看到了<heap nr="0">,而在我的测试中,malloc_stats()显示了许多竞技场的统计信息(另外:mallinfo()似乎也有限制,因为它只显示来自第零个竞技场的信息,这就是为什么我对它的测试与我在top中看到的内存使用情况不匹配的原因;此外,没有单个竞技场统计数据增长到足以触发我之前提到的错误)。 - Mike Tunnicliffe
我找不到malloc_info()的文档。 根据源代码,'if(options!= 0)return EINVAL' - http://sourceware.org/git /?p = glibc.git; a = blob; f = malloc / malloc.c; h = 558e8bab0ab3808ec9f5b569ca62863ef4651b27; hb = HEAD#l6323。 看起来它会遍历所有竞技场。 - leedm777
2
我的运行进程的标准输出被重定向到某个日志文件。因此,call malloc_stats() 没有在控制台上打印出来,而是在那个日志文件中。我花了将近一个小时才弄清楚这一点。 - JamesWebbTelescopeAlien

6
如果您能更改代码:
#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小时谷歌搜索中发现的方法之一) - Mike Tunnicliffe
1
发现了关于mallinfo()的一些有用信息;它似乎还没有准备好64位。返回的结构由int成员组成,无法处理超过4GB的字节大小。我没有找到任何修复此问题的证据,尽管我发现了Debian和RedHat的两个错误报告都被标记为NOTABUG/WONTFIX。 - Mike Tunnicliffe
重申一下我在戴夫的另一个回答下面的评论:mallinfo() 似乎也有限制,因为它只显示来自第零个竞技场的信息,这就是为什么我对它的测试与 top 报告的内存使用情况不匹配的原因;此外,没有单个竞技场统计数据增长到足以触发我之前提到的错误。malloc_stats() 显示了所有竞技场的信息。 - Mike Tunnicliffe

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