为什么C ++分配器会避免就地重新分配

时间:2014-08-31 20:54:19

标签: c++ memory memory-management stdvector

我对realloc的理解是,如果内存在分配点之外连续可用,它可以尝试扩展当前分配而不复制。

在阅读此https://github.com/facebook/folly/blob/master/folly/docs/FBVector.md时,我发现大多数分配器都避免了原地重新分配

  

。许多内存分配器不支持就地重新分配,尽管大多数内存分配器都可以。这来自现在臭名昭着的realloc()设计,它不透明地执行就地重新分配或分配memcpy-deallocate循环。这种缺乏控制随后迫使所有基于clib的分配器设计避免就地重新分配,包括C ++的new和std:allocator。

在另一个问题(Why is there no reallocation functionality in C++ allocators?)中回答了关于C ++中缺少重新分配器的问题,其中接受的答案提到这样的分配器会禁止重新分配使用C库,但是没有回答为什么不尝试重新分配如果可能,扩展当前内存?

3 个答案:

答案 0 :(得分:9)

答案 1 :(得分:-1)

扩展当前内存块的问题是分配器需要知道相邻内存块的状态。

假设分配器管理固定大小的块。让我们说所有托管块都是2的幂。在这种情况下,分配器会将块扩展到最接近的2的幂。其他任何东西都需要复制。

假设分配器使用队列管理变量大小的块?然后很难找到相邻的区块。

如上所述,经常不需要reallocs。获取新块和复制通常更有效。

答案 2 :(得分:-1)

尝试执行“就地重新分配”实际上没什么优势,因为常见的情况是没有空间来就地扩展已分配的内存块。任何好的分配器都将旨在避免碎片作为其首要任务之一 - 如果不这样做可能会导致内存需求的灾难性爆炸并迅速导致分配失败,大多数程序都无法处理,特别是在32位地址中空间。为了避免碎片化,分配器需要遵循最合适的策略。

因此,对于一个好的实际分配器,可以进行就地扩展的主要情况是没有先前释放的块可用,并且分配发生在“堆顶部”。对于非常简单的程序,只有一个分配被调整大小而在这些调整之间没有发生其他分配,因此就地扩展可能具有潜在的严重性能优势。这在用C编写的单线程程序中是合理的,但对于C ++程序来说并不是那么多,因为几乎所有的东西都会隐藏动态分配。