为什么malloc()是基于链表的
Why is malloc() based on linked-list?
在最坏的情况下,在大小为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需要基于链表。在不同平台之间,实现可能会发生变化。在一个平台上,速度可能至关重要,可以实现树,而在另一个平台中,内存更昂贵,为了节省尽可能多的内存,需要使用链表(或类似的)。
- Eclipse CDT clang 工具链 - 无法从链接器选项中删除 stdlibc++,但可以添加 libc++,E
- 如果我们不创建一个新节点并使用指针插入数据并建立链接(在链表中)怎么办?
- 是否可以使用另一个lua文件中定义的表,该表在当前文件中不需要作为模块
- 是否可以将同一组源数据与不同的表模型链接起来?
- 如何访问链表中链表中的成员
- 找不到'QAbstractItemViewPrivate'值的虚拟表的链接器符号
- 在Visual Studio 2010中使用大型查找表的链接限制使用代码库的限制
- 将十六进制数的 char[] 转换为对应于 ASCII 表中十六进制数字的字母的 char[] 并反转
- 链表的链表
- 将链接哈希表初始化为 NULL。获取"lvalue required as left operand of assignment"错误。为什么?这是我的代码:
- 索引链表(哈希表中的索引)的C++/STL 结构
- C++:运行时将共享对象与主机应用程序链接,符号表问题
- 哈希表单独链接中没有用于调用xxx的匹配函数
- 内存冲突:SIGSEGV 和"找不到虚拟表的链接器符号..."
- C++ 哈希表使用链接、删除方法
- 创建和链接双链表
- 如何使用链表来存储表,并在表中搜索项
- 创建一个由链接平衡最佳表和双链表组成的数据结构
- 链式哈希表的时间复杂度是多少?
- c++哈希表和链表的访问冲突