我听说过在 C++ 动态内存分配的上下文中多次使用“内存碎片”这个术语。我发现了一些关于如何处理内存碎片的问题,但找不到处理它本身的直接问题。所以:
还:
想象一下,你有一个“大”(32 字节)的可用内存:
---------------------------------- | | ----------------------------------
现在,分配其中的一些(5 个分配):
---------------------------------- |aaaabbccccccddeeee | ----------------------------------
现在,释放前四个分配,但不释放第五个:
---------------------------------- | eeee | ----------------------------------
现在,尝试分配 16 个字节。哎呀,我不能,即使有几乎两倍的免费。
在具有虚拟内存的系统上,碎片问题比您想象的要小,因为大分配只需要在 虚拟 地址空间中是连续的,而不是在 物理 地址空间中。所以在我的例子中,如果我有一个页面大小为 2 个字节的虚拟内存,那么我可以毫无问题地分配我的 16 个字节。物理内存如下所示:
---------------------------------- |ffffffffffffffeeeeff | ----------------------------------
而虚拟内存(更大)可能如下所示:
------------------------------------------------------... | eeeeffffffffffffffff ------------------------------------------------------...
内存碎片的典型症状是您尝试分配一个大块并且您不能,即使您似乎有足够的可用内存。另一个可能的后果是进程无法将内存释放回操作系统(因为它从操作系统分配的每个大块,用于malloc细分等等,都留下了一些东西,即使每个块的大部分现在未使用)。
malloc
C++ 中防止内存碎片的策略是根据对象的大小和/或预期的生命周期从不同的区域分配对象。因此,如果您要创建大量对象并稍后将它们全部销毁,请从内存池中分配它们。您在它们之间进行的任何其他分配都不会来自池,因此不会位于它们之间的内存中,因此内存不会因此而碎片化。或者,如果您要分配大量相同大小的对象,则从同一个池中分配它们。然后,池中的一段可用空间永远不会小于您尝试从该池分配的大小。
通常你不需要太担心它,除非你的程序是长时间运行的并且做了很多分配和释放。当您同时拥有短期和长期对象时,您的风险最大,但即便如此,您malloc也会尽最大努力提供帮助。基本上,忽略它,直到您的程序分配失败或意外导致系统内存不足(在测试中抓住这一点,优先考虑!)。
标准库并不比其他任何分配内存的库差,并且标准容器都有一个Alloc模板参数,如果绝对必要,您可以使用它来微调它们的分配策略。
Alloc