C++:这看起来像内存碎片吗

C++: Does this look like memory fragmentation?

本文关键字:内存碎片 看起来 C++      更新时间:2023-10-16

摘要:

我有一个应用程序消耗的内存远远超过了它应该消耗的内存(大约是预期量的250%),但我似乎找不到任何内存泄漏。调用同一个函数(进行大量分配)将在一定程度上不断增加内存使用量,然后它就不会改变并保持不变。

程序详细信息:

应用程序使用四叉树数据结构来存储"点"。可以指定要存储在内存中的最大点数(缓存大小)。"Points"存储在"PointBuckets"(链接到四叉树叶节点的点阵列)中,如果达到四叉树中的最大点总数,这些点将被序列化并保存到临时文件中,以便在需要时检索。这一切似乎都很好。

现在,当加载一个文件时,会创建一个新的四叉树,如果存在旧的,则会删除它,然后从文件中读取点,并逐个插入到四叉树中。在节点拆分等过程中,当创建和删除存储桶时,会进行大量内存分配。

症状:

如果我加载一个预期使用300MB内存的文件一次,我就会得到预期的内存消耗量。一切都很好。如果我一次又一次地加载同一个文件,内存使用量就会不断增长(我看到的是顶部的RES列,Linux),直到大约700MB。这可能表明内存泄漏。然而,如果我继续加载文件,内存消耗将保持在700MB。

另一件事:当我使用valgrind massif并查看内存使用情况时,它总是保持在预期的范围内。例如,如果我将缓存大小指定为1.5GB并单独运行程序,它最终将消耗4GB的内存。如果我在massif中运行它,它将一直保持在2GB以下,然后在生成的图中,我可以看到它实际上从未分配超过预期的1.5GB。我天真的假设是,发生这种情况是因为massif使用了一个自定义内存池,以某种方式防止碎片。

那么你认为这里发生了什么?如果是内存碎片,我应该寻找什么样的解决方案来解决这个问题?

我更倾向于简单的分配器和操作系统缓存行为。它们会保留你分配的内存,而不是释放内存,以便下次你请求时可以更及时地将其返回给你。然而,250%听起来确实有很多这种效果-你可能会遇到碎片问题。

试着把分配器换成一个无碎片的分配器,比如对象池或内存竞技场。