malloc lab
隐式空闲链表(书本)
基本设计
在博客CSAPP动态内存分配 中,我们已经详细介绍了隐式空闲链表的分配原理了。那么我们这次就来手动实现一个简单的分配器
首先我们来介绍一下分配器需要输出给应用程序的三个函数:
extern int mm_init(void)
这个函数的作用是初始化分配器,如果成功,那么就返回0;否则就返回-1
extern void *mm_malloc(size_t size)
这个函数就是分配空间
extern void mm_free(void *ptr)
这个函数是释放空间
我们要申请的块格式如下,具有头部和尾部,最小的块大小为16字节:
整一个隐式空闲链表如下图所示:
第一个字是一个双字边界对齐的不使用的填充字。填充后面紧跟着一个特殊的序言块。这是一个8字节的已分配块,只由头部和尾部组成。序言块是在初始化的时候创建的,并且是永不释放的。在序言块的后面紧跟着的是零个或者多个由mallock或者free调用创建的普通块。在结尾处,是一个大小为0的已分配块,只由一个头部组成。
序言块和结尾块是一种消除合并时边界条件的技巧。
宏介绍
1 |
|
mm_init
mm_init函数从内存系统得到4个字,并将其初始化,创建一个空的空闲链表。然后它调用extend_heap函数。这个函数将堆扩展CHUNKSIZE
字节,并且创建初始的空闲块。
1 | int mm_init(void) |
现在,分配器已经初始化了,并且准备好接受来自应用的分配和释放请求
extend_heap
这个函数当堆被初始化的时候或者当mm_malloc
不能找到一个合适的分配块的时候。为了保持对齐,extend_heap会将其请求大小向上舍入为最接近的2字(8字节)的倍数,然后向内存系统请求额外的堆空间
1 | static void *extend_heap(size_t words) |
mm_free 函数
1 | void mm_free(void *bp) |
free函数可以释放一个以前分配的块,这个函数释放所请求的块bp,然后我们将其与邻接的空闲块合并起来
coalesce函数
coalesce函数就是将空闲块合并起来的函数,其函数示意图如下
1 |
|
mm_malloc函数
应用会通过调用mm_malloc
函数来向内存请求大小为size字节的块。在检查完请求的真假之后,分配器必须调整请求快的大小,从而为头部和脚部留有空间并满足双字对齐的要求。
1 | void *mm_malloc(size_t size) |
find_fit函数
这里,我们采取的方法是first_fit,也就是找到第一个符合条件的block来放置。
1 | static void *find_fit(size_t size) |
最佳适配
1 | static void *best_fit(size_t asize){ |
place函数
place函数就是将此适配的块的头部和尾部进行修改,如果剩下的尺寸超过16,则将其重新加入空闲块中,避免内部碎片;
1 | static void place(void *bp, size_t asize) |
mm_realloc函数
realloc
函数就是将旧的块中的内容复制到新的块当中去
1 | void *mm_realloc(void *ptr, size_t size) |