想象一下,您拥有“大”(32字节)的空闲内存空间:
----------------------------------
| |
----------------------------------
现在,分配其中一些(5个分配):
----------------------------------
|aaaabbccccccddeeee |
----------------------------------
现在,释放前四个分配,但不释放第五个分配:
----------------------------------
| eeee |
----------------------------------
现在,尝试分配16个字节。糟糕,即使有那么多的免费,我也无法做到。
在具有虚拟内存的系统上,碎片化的问题比您想象的要少,因为大型分配只需要在虚拟地址空间中是连续的,而不是在物理地址空间中是连续的。因此,在我的示例中,如果我的虚拟内存的页面大小为2字节,则可以毫无问题地进行16字节分配。物理内存如下所示:
----------------------------------
|ffffffffffffffeeeeff |
----------------------------------
而虚拟内存(更大)可能如下所示:
------------------------------------------------------...
| eeeeffffffffffffffff
------------------------------------------------------...
内存碎片的经典症状是,即使您似乎有足够的可用内存,您还是尝试分配一个大块而您却无法分配。另一个可能的结果是该进程无法将内存释放回OS(因为它从OS分配的所有块中仍然有一些对象在使用中,即使这些块现在几乎未使用)。
防止C ++中内存碎片的策略是根据对象的大小和/或预期寿命从不同区域分配对象而进行的。因此,如果要创建很多对象并在以后将它们全部销毁,请从内存池中分配它们。您在它们之间进行的任何其他分配都不会来自池,因此不会在内存中位于它们之间,因此不会导致内存碎片。
通常,您不必担心太多,除非您的程序长时间运行并且需要进行大量分配和释放。在这种情况下,您面临的风险最大的是短寿命和长寿命的混合物,即使malloc
那样,它也将尽最大努力为您提供帮助。基本上,请忽略它,直到您的程序出现分配失败或意外导致系统内存不足时为止(在测试中捕获此优先)!
标准库并不比分配内存的其他任何库差,并且标准容器都有一个Alloc
模板参数,如果绝对必要,可以使用它们来微调其分配策略。