什么是内存碎片

想象一下,您拥有“大”(32字节)的空闲内存空间:

----------------------------------
|                                |
----------------------------------

现在,分配其中一些(5个分配):

----------------------------------
|aaaabbccccccddeeee              |
----------------------------------

现在,释放前四个分配,但不释放第五个分配:

----------------------------------
|              eeee              |
----------------------------------

现在,尝试分配16个字节。糟糕,即使有那么多的空闲内存,我也无法分配。

在具有虚拟内存的系统上,碎片化的问题比您想象的要少,因为大型分配只需要在虚拟地址空间中是连续的(虚拟地址映射到物理地址),而不需要在物理地址空间中是连续的因此,在我的示例中,如果我的虚拟内存的页面大小为32字节,那么我可以毫无问题地进行16字节分配。物理内存如下所示:

----------------------------------
|ffffffffffffffeeeeff            |
----------------------------------

而虚拟内存(更大)可能看起来像这样:

------------------------------------------------------...
|              eeeeffffffffffffffff                   
------------------------------------------------------...

内存碎片的经典症状是,即使您似乎有足够的可用内存,您也尝试分配一个大块而您却无法分配。另一个可能的结果是该进程无法将内存释放回OS(因为从OS分配的所有块中仍然有一些对象在使用中,即使这些块现在几乎未使用)。

防止C ++中内存碎片的策略是根据对象的大小和/或预期寿命从不同区域分配对象来进行工作的。因此,如果要创建很多对象并在以后将它们全部销毁,请从内存池中分配它们。您在它们之间进行的任何其他分配都不会来自池,因此不会在内存中位于它们之间,因此不会导致内存碎片。

通常,除非您的程序可以长时间运行并且需要大量分配和释放,否则您不必为此担心。在这种情况下,您面临的风险最大的是短寿命和长寿命的混合物,但即使malloc那样,它也会尽最大努力提供帮助。基本上,请忽略它,直到您的程序出现分配失败或意外导致系统内存不足(优先选择在测试中捕获!)。

标准库不比分配内存的任何其他库差,并且标准容器都有一个Alloc模板参数,如果绝对必要,可以使用它们来微调其分配策略。

posted @ 2019-10-23 09:57  strive-sun  阅读(1387)  评论(0编辑  收藏  举报