为什么malloc()是基于链表的

Why is malloc() based on linked-list?

本文关键字:链表 于链表 malloc 为什么      更新时间:2023-10-16

在最坏的情况下,在大小为n的内存段(这是正确的术语吗?)上,链表需要O(n)时间来分配合适大小的内存块。

然而,如果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。我看到了可遍历内存池的数据结构问题,但作者似乎还没有弄清楚。

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

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

在大多数系统中,每个malloc(几乎)正好有一个free,所以如果你让一个更快,让另一个更慢,你得到的收益很小。

"下一个分配与上一个相同"也是相对常见的,这意味着如果最后一个分配在列表中的第一个,则是O(1)运算。

在实时系统中,bucket通常用于分配,因此有许多固定的大小,每次从主堆中分配一些东西时,大小都会四舍五入到最接近的较大大小,当释放时,它会进入该大小的bucket(即链表)。如果已经有这样大小的空闲元素,则使用该分配。除了分配/空闲的速度为O(1)之外,这还有减少碎片的好处——"把所有堆都撕成小块,然后就没有任何大块了"并非完全不可能,但至少不可能通过每次多分配一个字节来占用大部分内存,直到一次分配中有一半的堆大小。

(此外,在Linux的GLIBC中,超过一定大小的分配根本不会出现在链表中——它们通过mmap直接分配,并在调用free时与munmap一起释放)

最后,算法的复杂性并不是一切——在现实生活中,重要的是花在某件事上的实际时间——即使算法有O(n),但每次运算都很快,它也可以击败O(logn)。类似地,特别是在C++中,小的分配非常占主导地位,这意味着每个节点更多内存的开销是一个重要因素。

没有任何规范规定malloc需要基于链表。在不同平台之间,实现可能会发生变化。在一个平台上,速度可能至关重要,可以实现树,而在另一个平台中,内存更昂贵,为了节省尽可能多的内存,需要使用链表(或类似的)。