如何迭代所有malloc块(glibc)

时间:2016-06-23 10:00:46

标签: c++ debugging gdb malloc

我正在尝试迭代所有竞技场中的所有malloc_chunk。 (基于核心文件调试,用于内存泄漏和内存损坏调查)

我知道每个竞技场都有 top_chunk 指向一个竞技场内的顶部块,基于 top_chunk ,在其中,有 prev_size size ,基于代码(glibc / malloc / malloc.c): enter image description here 我可以获得之前的连续块,然后在一个场地中循环所有块。 (我可以统计大小和数量的块,如WinDBG:!heap -stat -h)并且还基于 prev_size size ,我可以检查大块是否腐败。

在竞技场(malloc_state)中,有一个成员变量: next 指向下一个竞技场。然后我可以循环所有竞技场的块。

但我遇到的一个问题是如果没有分配块,prev_size无效,如何获取以前的malloc_chunk?或者这种方式不正确。

问题背景:

我们遇到的内存泄漏错误是在几个在线数据节点(我们的项目是分布式存储集群)中报告的内存泄漏。

我们做了什么和结果:

  1. 我们使用valrgind来重现测试集群中的错误,但遗憾的是我们什么都没得到。

  2. 我试图调查有关堆的更多信息,尝试分析堆块,并按照我之前在WinDBG中执行的方式(它有非常有趣的堆命令来挖掘内存泄漏和内存损坏),但我被我提出的问题阻止了。

  3. 我们使用valgrind-massif来分析分配(我认为它非常详细和有趣,可以显示哪个分配占用了多少内存)。 Massif显示了几条线索,我们按照这个并检查代码,最后发现了泄漏(地图非常庞大,并且正确使用它,但我会删除持有者类的析构函数,这就是为什么valgrind不报告这个)。 / p>

  4. 我将更多地了解gdb-heap源代码,以了解有关glic malloc结构的更多信息。

3 个答案:

答案 0 :(得分:1)

首先,在深入研究malloc的实现细节之前,您可以更好地利用valgrind之类的工具,或者甚至在MALLOC_CHECK_环境变量下运行,让内部堆一致性检查为您完成工作。

但是,既然你问了......

glibc malloc.c对于查看上一个块有一些有用的评论。

一些特别有趣的是:

/* Note that we cannot even look at prev unless it is not inuse */

If prev_inuse is set for any given chunk, then you CANNOT determine the size of the previous chunk, and might even get a memory addressing fault when trying to do so.

这只是malloc implimentation的限制。当使用上一个块时,将存储该大小的页脚由分配的用户数据使用。

虽然它对您的情况没有帮助,但您可以按照prev_inuse宏的作用来检查上一个块是否正在使用。

#define PREV_INUSE 0x1
#define prev_inuse(p) ((p)->size & PREV_INUSE)

它检查当前块大小的低位。 (所有块大小都可被4整除,因此较低的2位可用于状态。)这将有助于您在进入无人区之前停止迭代。

不幸的是,在访问每个块之前,你仍然会提前终止你的循环。

如果你真的想迭代所有块,我建议你从malloc_state::top开始,然后按next_chunk直到next_chunk指向top

答案 1 :(得分:1)

免费的开源程序https://github.com/vmware/chap在这里为glibc malloc提供了您想要的功能。只需抓住一个核心(要么是因为核心崩溃了,要么是通过使用gcore或从gdb内使用generate命令来获取lib核心)。然后只需打开内核即可:

chap yourCoreFileName

到达chap提示符后,如果要遍历所有块(包括空闲和不空闲),则可以根据所需的详细程度执行以下任何操作,但请记住,“分配”在chap中不包含块头,而是从malloc返回的地址开始。

尝试以下任何一种方法:

count allocations
summarize allocations
describe allocations
show allocations

如果您只关心当前正在使用的分配,请尝试以下任何一种方法:

count used
summarize used
describe used
show used

如果您只关心泄漏的分配,请尝试以下任何一种方法:

count leaked
summarize leaked
describe leaked
show leaked

更多细节可从上述github URL中获得的文档中找到。

就损坏而言,chap在启动时会进行一些检查并报告许多损坏,尽管有时输出可能会有点晦涩。

答案 2 :(得分:0)

尝试使用pmap <PID> -XX命令从各个方面跟踪内存使用情况。