
实现
一个动态内存申请器,能实现:malloc, free, realloc;
前置知识
CSAPP第9章:动态内存申请器,内存中的堆,链表;
蛋疼的检测工具
首先需要;
1 | gcc -Wall -O2 -m32 -c -o mdriver.o mdriver.c |
然后;
1 | make mdriver mdriver.o mm.o memlib.o fsecs.o fcyc.o clock.o ftimer.o |
以上两个出错请用下面指令解决;
1 | sudo apt-get install gcc-multilib |
下载出错请更新镜像,或者添加清华园下载路径:
1 | deb http://mirrors.tuna.tsinghua.edu.cn/kali kali-rolling main contrib non-free |
输入以下命令打开下载源:
1 | sudo vim /etc/apt/sources.list |
按 i 进入编辑模式,完成后输入 :w 保存, :q退出;之后输入一遍:
1 | sudo apt-get update && apt-get upgrade && apt-get dist-upgrade |
然后就能输入第三条指令了,接着编译就行了;
其次,traces是缺失的,需要下载以进行检测;地址:
https://github.com/Davon-Feng/CSAPP-Labs/tree/master/yzf-malloclab-handout/traces
将10个文件装入文件夹,将文件夹放到和 mdriver 同级的地方;
并修改config.h里第15行的内容为自己的traces文件夹目录;
分析
- 需要内存空间模拟堆;
- 需要模拟已分配和未分配的块;
- 需要管理这个空间(开始,结束,填充);
- 需要操控这个空间(放置,分割,合并,释放);
已知内容
mem_heap,mem_brk两个指针分别指向堆的开始和结尾,mem_sbrk函数可以调节brk并返回旧brk的值,两个指针已初始化相等;
堆中的最小单位为4字节(1字),第一个字是双字边界对齐不使用的填充字;后面跟着两字的序言块,分配器使用私有的全局变量 heap_listp 指向序言块的第二个字开头;以一个0内容的已分配块作为结束的一个字;
使用隐式空闲链表,下一次适配,边界标记的堆块格式(最小4字,开头和结尾2字是标志字),立即合并;
标志字由整个块的大小或上分配位组成;
代码
I . 操作空闲链表的常数和宏
1 |
|
p是一个void * 指针,所以强制转换是必要的;
II . 创建空闲列表(堆)
1 | int mm_init(void) |
mm_init函数在创建初始堆空间;extend_heap函数在延展空闲块,用在init里,当然也可以用在当申请空间不足时的地方,所以单独成为一个函数;coalesce之后会讲到,是合并空闲块的函数,在填充和释放时用到;
注意,首次适配所记录的当前块指针如果被向前合并,则记录指针也需要随之改变,所以最好运用合并函数的地方都使其返回的值成为prev_listp;
III . 释放和合并块
1 | void mm_free(void * bp) |
在第二个else if 的地方,HDRP需要写前面,因为FTRP会用HDRP处的内容;
IV . 放置和分割块
1 | void *mm_malloc(size_t size) |
V . 重分配块大小
1 | void *mm_realloc(void *bp, size_t size) |
VI . 检测
将代码打包到mm.c,使用之前的编译命令,搞出有代码的 mdriver;输入以检测:
1 | ./mdriver -V |
如图:

总结
至此,实现了所分析的内容:
模拟空间,填充——extend_heap;
已分配和未分配的块——有头尾的列表模式以及宏定义的操作;
开头结尾——mm_init;
以及有小标题的放置,分割,释放,合并小函数;

















































































































