链接列表。在哪里分配以及如何应对碎片?

时间:2013-04-30 05:56:16

标签: c memory-management

  • 地点
      堆中的
    • ,碎片化(每个节点的malloc) - 以多种不同的方式有效(缓慢分配,访问速度慢,内存碎片化)
    • 在堆中,在一个大块中 - 当需要重新分配时,数据结构获得的所有灵活性都会丢失
    • 堆栈中的
    • - 堆栈的大小往往相当有限,因此不建议在其上分配大型结构

他们的巨大优势,即插入O(1),在碎片化内存的环境中看起来相当无用,并且数千次调用内存分配器给我们另外10个字节。


编辑澄清:
在接受采访时询问了这个问题。这不是一个工作场所的问题,所以通常的启发式方法是希望盲目地从一小组标准算法中找出正确的决策而不适用。

现有的答案和评论提到“malloc不是那么慢”,“malloc部分地对抗碎片化”。好吧,如果我们使用另一种数据结构,例如C ++向量的C端口(即 - 分配足够大小的顺序内存,如果数据扩展,重新分配到两倍大的块),所有问题都解决了,但我们放松了快速插入/删除。链接列表(分配在哪里?)的任何场景都具有广泛的向量优势?

5 个答案:

答案 0 :(得分:7)

这听起来像是过早优化。我认为正确的方法是:

  1. 尽可能使用最简单的实现;
  2. 描述整个计划。
  3. 如果分析显示列表存在性能问题,请考虑替代实现(包括备用分配器)。

答案 1 :(得分:4)

如果您担心标准分配器无法有效处理专用的10字节分配,请编写一个自定义分配器,从标准(malloc())分配器中获取大块内存,并有效地分发小项目。当你在最初的大块中耗尽内存时,你应该重新分配;你应该分配一个新的(额外的)大块并从中分配。您可以决定如何处理释放的内存。您可以简单地忽略版本,直到您在使用列表处理结束时释放所有大块。或者你可以通过跟踪大块的释放内存来使生活复杂化。这样可以减少整体内存使用量,但最初编写起来会更复杂。

另一方面,您应该意识到过早优化的风险。你有没有测量过性能?鉴于我在你最近的问题中所看到的,你应该坚持使用malloc()而不是尝试编写自己的分配器(

)。

答案 2 :(得分:0)

这可能不是确切的解决方案,而是另一种方法

  • 自行处理碎片。
    • 分配大池记忆
    • 为每个新节点提供此节点的内存,直到有空闲内存。
    • 如果使用了池,请分配另一个池并使用它来分配新块

然而,这说起来容易做起来难。你可能会遇到很多问题。

因此,建议对malloc和相关函数进行此类优化。

从堆栈分配不是一个可行的选择。您无法从堆栈中malloc。您将不得不在某些功能中预先分配大块缓冲区。在这种情况下,数组比链表更好。

答案 3 :(得分:0)

理想情况下,您的链接列表实现不应使用上述任何一种。应该由调用者来分配和销毁内存。考虑像sprintffgets等函数......他们分配任何内存吗?不,这是有原因的:简单。想象一下,如果你必须freefgets获得的所有内容(或更糟糕的是,fscanf)。难道不痛苦吗?尝试开发您的功能以与标准库保持一致。

声明listnode_alloc函数可能会有所帮助,但这只会包含malloclistnode_init函数。考虑realloc如何处理NULL输入...

答案 4 :(得分:0)

好吧,内存分配策略可能会因内存碎片,成千上万的系统调用等而有所不同,这就是使用O的原因! ; - )