【问题标题】:Why do C++ allocators avoid in-place reallocation为什么 C++ 分配器避免就地重新分配
【发布时间】:2014-10-25 02:45:20
【问题描述】:

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

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

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

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

【问题讨论】:

  • 可能是因为它做了很多工作却没有多少好处,而且它使事情变得更加混乱,特别是当你混合使用构造函数和析构函数时(例如,你会得到两种不同的行为,具体取决于关于它是否重新分配,因为在一种情况下会调用一堆复制构造函数和析构函数,而在另一种情况下则不会)。
  • @MichaelAaronSafyan 因此,realloc 是一个 C 库函数,如果数据完全复制到其他地方,它不能确保调用析构函数,这是调整大小的原因,我们做类似的事情为适当大小的数据调用 malloc,复制对象并在先前分配上调用析构函数?
  • 我不知道为什么事情是按照原来的方式设计的。我只是在猜测它以及可能阻止它的一些明显困难/障碍。
  • @MichaelAaronSafyan:如果每次有人回答“为什么 X 不做 Y”我都能得到一分钱就好了?下意识地“因为这是无益的大量工作”......

标签: c++ memory memory-management stdvector


【解决方案1】:

【讨论】:

  • +1 因为没有像每个人那样试图为现状辩护。
  • @Mehrdad 问题标题是“Why do C++ allocators Avoid in-place reallocation”,其他答案都在回答这个问题。
【解决方案2】:

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

因此,对于一个优秀的现实世界分配器,可以进行就地扩展的主要情况是没有可用的先前释放的块,并且分配发生在“堆顶”。对于非常简单的程序,其中仅调整单个分配的大小而在这些调整大小之间没有发生其他分配,就地扩展可能会带来严重的性能优势。这在用 C 编写的单线程程序中是合理的,但对于 C++ 程序来说并非如此,因为几乎在您所做的所有事情中都在进行隐藏的动态分配。

【讨论】:

  • 如果优势如此之小,那您为什么认为会有添加该功能的提议?
  • 你真的认为某件事必须是一个好主意才能有人提出建议吗?
  • @R..:在你得出结论之前,请检查提案中的名称及其讨论。
  • @BenVoigt:但是你是否反对我的推理而不仅仅是诉诸权威?也许我遗漏了一些东西,但我在分配方面的经验是,就地扩展的机会很少,除非在人为条件下或整体分配器策略不好的情况下。
  • @R..:因人而异?有些人确实倾向于提出比其他人更好的想法。你的反对只是挥手致意的“这不是常见的情况”,而实际上人们似乎已经有足够的问题让他们认为它值得修复,所以显然它很常见,很重要。除非您认为这些人不知道如何正确衡量绩效,否则您不能真正声称他们错了。
【解决方案3】:

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

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

假设分配器使用队列管理可变大小的块?那么就很难找到相邻的区块了。

如上所述,重新分配并不需要那么频繁。通常只抓取一个新块并复制会更有效。

【讨论】:

  • -1 这不是原因。如果分配器不能就地重新分配,那么它就不会。没有必要仅仅因为某项功能可能不会被使用而禁止它。
  • 我没有说它会被禁止。我是说在某些内存分配方法下,重新分配是不切实际的,因为他们根本不这样做。
  • 哈哈,看起来我不小心给了你投票而不是给你投票。
  • 什么?我只看到一个赞成票,那是我的。不确定您指的是什么“其他人”。
  • 您是说如果您使用支持此类功能的队列会很困难,而您可以使用伙伴系统之类的东西来做到这一点。那么有理由更喜欢排队吗?
猜你喜欢
  • 2011-03-07
  • 2011-01-22
  • 2010-11-23
  • 1970-01-01
  • 2010-10-07
  • 2023-02-02
  • 2021-04-24
  • 2012-07-21
  • 1970-01-01
相关资源
最近更新 更多