我正在尝试迭代所有竞技场中的所有malloc_chunk。 (基于核心文件调试,用于内存泄漏和内存损坏调查)
我知道每个竞技场都有 top_chunk 指向一个竞技场内的顶部块,基于 top_chunk ,在其中,有 prev_size 和 size ,基于代码(glibc / malloc / malloc.c): 我可以获得之前的连续块,然后在一个场地中循环所有块。 (我可以统计大小和数量的块,如WinDBG:!heap -stat -h)并且还基于 prev_size 和 size ,我可以检查大块是否腐败。
在竞技场(malloc_state)中,有一个成员变量: next 指向下一个竞技场。然后我可以循环所有竞技场的块。
但我遇到的一个问题是如果没有分配块,prev_size无效,如何获取以前的malloc_chunk?或者这种方式不正确。
问题背景:
我们遇到的内存泄漏错误是在几个在线数据节点(我们的项目是分布式存储集群)中报告的内存泄漏。
我们做了什么和结果:
我们使用valrgind来重现测试集群中的错误,但遗憾的是我们什么都没得到。
我试图调查有关堆的更多信息,尝试分析堆块,并按照我之前在WinDBG中执行的方式(它有非常有趣的堆命令来挖掘内存泄漏和内存损坏),但我被我提出的问题阻止了。
我们使用valgrind-massif来分析分配(我认为它非常详细和有趣,可以显示哪个分配占用了多少内存)。 Massif显示了几条线索,我们按照这个并检查代码,最后发现了泄漏(地图非常庞大,并且正确使用它,但我会删除持有者类的析构函数,这就是为什么valgrind不报告这个)。 / p>
我将更多地了解gdb-heap源代码,以了解有关glic malloc结构的更多信息。
答案 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
命令从各个方面跟踪内存使用情况。