CMU15213 笔记:malloc
CMU15213 笔记:malloc
CS15-213 lab notes
动态内存分配
如图所示进程的虚拟内存区域,内核维护着一个变量 brk,它指向堆的顶部。
malloc 和 free 函数
在 32 位机中,malloc 返回的块的地址总是 8 的倍数,在 64 位机中,该地址总是 16 的倍数。
为了实现动态的内存分配,可以使用 sbrk 函数。
释放内存空间的 free 函数。
碎片
内部碎片是指:内部碎片就是已分配块大小和它们的有效载荷大小之差的和,在任意时刻,内部碎片的数量只取决于以前请求的模式和分配器的实现方式。
外部碎片是指:是当空闲内存合计起来足够满足一个分配请求,但是没有一个单独的空闲块足够大可以来处理这个请求时发生的。
涉及的问题
需要处理以下问题:
隐式空闲链表
定义块的数据结构:
这里需要注意的是,malloc 的返回值为有效载荷的开始处,而不是块的开始处。
8 字节对齐的地址特征,其地址数值的 16 进制表示的最后一个字符为 0。
以 8 字节对齐,可以使对 long,double 进行操作时,不会产生 bus error。
malloc is supposed to return a pointer “which is suitably aligned for any built-in type”.
由于 8 字节对齐,块大小的最低 3 位总是零。因此寻址块,只需要高 29 位,剩余的 3 位可以用来编码其他信息。所以有如下所示的头部信息:
隐式空闲链表结构
如下图所示:
之所以称之为隐式空闲链表,是因为空闲块是通过头部中的大小字段隐含地连接着地。分配器可以通过遍历堆中的所有地块,从而间接地遍历整个空闲块地集合。通过设置一个已分配位而大小为 0 的终止头部。来作为结束标记。
优缺点
隐式空闲链表的实现简单,显著的缺点是,任何操作的开销都要对,空闲链表进行搜索,该搜索所需时间与堆中已分配块和空闲块的总数呈线性关系。
合并空闲块
如图所示,当申请一个 4 字的有效载荷时,并不能申请到,因为单独每个空闲块,只有 3 个多的字可以使用(因为块头部需要使用一些空间),虽然相邻的块合计大小是大于 4 字的:
当分配器释放一个已分配的块时,可能其他空闲块与这个新释放的空闲块相邻,这些邻接的空闲块可能引起一种现象,叫做假碎片。就是有许多可用的空闲块被切割成为小的,无法使用的空闲块。
带边界标记的合并
这个脚部总是在距离当前块起始位置一个字的距离,由于每个块都要有 header 和 footer,所以当分配的都是小块时,会很浪费空间。如下图所示的优化方法:
也就是在如下图所示的情况下:
将 m1 块的 footer 的已分配/空闲块的信息,放在 n 块的多余的空闲位中。
代码
定义一些必要的宏函数,从课本上抄下来,如下所示:
最后需要实现的是 find_fit 函数和 place 函数,如下所示:
测试结果
使用隐式链表法
得到如下结果:
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧