为什么malloc()基于链表?

时间:2015-06-29 07:26:56

标签: c++ c memory memory-management data-structures

在最坏的情况下,在大小为n的内存的一个部分(这是正确的术语?)上,链接列表需要O(n)时间来分配合适大小的内存块。< / p>

但是,如果malloc是基于树的,例如,间隔树,则只需要O(logn)时间。此外,树可以满足这样的要求而没有额外的时间(就时间复杂度而言)为"Find the smallest block of free memory whose size is larger them x ""Always allocate on the borders of free memory""Free only a part of the allocated memory"。一个缺点可能是释放内存需要O(logn)时间。

由于

PS。我已经看到了Data structures for traversable memory pool这个问题,但作者似乎并没有想到这个问题。

2 个答案:

答案 0 :(得分:3)

我不知道答案,但这里有一些想法:

绝对没有malloc以特定方式实施的要求。但是,在最坏的情况下,不平衡树与链表一样糟糕。平衡的链表是更多的维护。每个节点有两个链接的树也比单链表占用更多内存。删除链表中的节点更容易,最后插入非常容易。

在大多数系统中,每free(几乎)只有一个malloc - 所以如果你通过让另一个更慢来制作一个更快,那么你获得的收益很少。

“下一个分配与前一个分配相同”也是相对常见的,这意味着如果最后一个分配是列表中的第一个,则它是O(1)操作。

在实时系统中,存储桶通常用于分配,因此存在许多固定大小,并且每次从主堆分配某些内容时,大小将四舍五入到最接近的较大大小,并且释放它进入那个大小的桶(这是一个链表)。如果已存在该大小的自由元素,则使用该分配。除了分配/自由为O(1)的速度之外,这还有减少碎片的好处 - 并非完全不可能“将所有堆碎成小块,然后没有留下任何大块”,但它至少不是通过简单地每次分配一个字节来占用大部分内存,直到你在一次分配中有一半的堆大小。

(另外,在Linux的GLIBC中,超过特定大小的分配根本不会在链接列表中结束 - 它们直接通过mmap分配,并在munmap时以free释放。被称为)

最后,算法的复杂性并非一切 - 在现实生活中,它是在重要事物上花费的实际时间 - 即使算法具有O(n)但每个操作都很快,它可以击败O(logn)。同样,特别是在C ++中,小分配占据主导地位,这意味着每个节点更多内存的开销是一个重要因素。

答案 1 :(得分:0)

没有说明malloc需要基于链表的规范。在平台之间,实施可能会改变。在一个平台上,速度可能是至关重要的,并且可以实现树,在另一个平台上,内存更昂贵,并且使用链表(或类似)来节省尽可能多的内存。