diff --git a/malloclab/malloc b/malloclab/malloc deleted file mode 100755 index 1cd23c2..0000000 Binary files a/malloclab/malloc and /dev/null differ diff --git a/malloclab/mm.c b/malloclab/mm.c index 76c3fda..ff337cd 100644 --- a/malloclab/mm.c +++ b/malloclab/mm.c @@ -28,49 +28,49 @@ ********************************************************/ team_t team = { /* 团队名字 */ - "Tom is a Cat", + "8-Bit Brainstorm", /* 团队老大的名字 */ - "Tom", + "Cikki", /* 团队老大的email地址 */ - "Tom@sina.com", + "c_gh0s7@nudt.edu.cn", /* 团队其他成员的名字 (如果没有,就空着) */ "", /* 团队其他成员的email地址 (如果没有,就空着) */ ""}; -/* 单字 (4) 还是双字 (8) 边界对齐 */ -#define ALIGNMENT 8 - -/* 舍入到最近的ALIGNMENT边界上 */ -#define ALIGN(size) (((size) + (ALIGNMENT - 1)) & ~0x7) - +/* 基本常量和宏定义 */ +#define ALIGNMENT 8 /* 将块对齐到8字节(双字) */ +#define ALIGN(size) \ + (((size) + (ALIGNMENT - 1)) & ~0x7) /* 向上舍入到最近的8的倍数 */ #define SIZE_T_SIZE (ALIGN(sizeof(size_t))) -// 定义块头部和尾部的大小 -#define WSIZE 4 // 字大小(4字节) -#define DSIZE 8 // 双字大小(8字节) -#define CHUNKSIZE (1 << 12) // 扩展堆的默认大小(4KB) +/* 内存分配器的关键参数 */ +#define WSIZE 4 /* 字(word)的大小 = 4字节 */ +#define DSIZE 8 /* 双字(double word)的大小 = 8字节 */ +#define CHUNKSIZE (1 << 12) /* 扩展堆时的默认大小 = 4096字节 = 4KB */ -// 将大小和分配位打包成一个字 -#define PACK(size, alloc) ((size) | (alloc)) +/* 用于操作头部和脚部的宏 */ +#define PACK(size, alloc) ((size) | (alloc)) /* 将大小和已分配位打包成一个字 \ + */ +#define GET(p) (*(unsigned int *)(p)) /* 读取指针p处的一个字 */ +#define PUT(p, val) (*(unsigned int *)(p) = (val)) /* 在指针p处写入一个字 */ -// 读取和写入地址p处的字 -#define GET(p) (*(unsigned int *)(p)) -#define PUT(p, val) (*(unsigned int *)(p) = (val)) +/* 从头部或脚部获取大小和已分配位 */ +#define GET_SIZE(p) (GET(p) & ~0x7) /* 获取块大小,去掉低3位的标志位 */ +#define GET_ALLOC(p) (GET(p) & 0x1) /* 获取已分配位(0=空闲,1=已分配)*/ -// 从地址p读取大小和分配位 -#define GET_SIZE(p) (GET(p) & ~0x7) -#define GET_ALLOC(p) (GET(p) & 0x1) +/* 给定块指针bp,计算块的头部和脚部位置 */ +#define HDRP(bp) ((char *)(bp) - WSIZE) /* 指向块头部的指针 */ +#define FTRP(bp) \ + ((char *)(bp) + GET_SIZE(HDRP(bp)) - DSIZE) /* 指向块脚部的指针 */ -// 计算块的头部和尾部地址 -#define HDRP(bp) ((char *)(bp) - WSIZE) -#define FTRP(bp) ((char *)(bp) + GET_SIZE(HDRP(bp)) - DSIZE) +/* 给定块指针bp,计算下一个和前一个块的地址 */ +#define NEXT_BLKP(bp) \ + ((char *)(bp) + GET_SIZE(((char *)(bp) - WSIZE))) /* 下一个块的指针 */ +#define PREV_BLKP(bp) \ + ((char *)(bp) - GET_SIZE(((char *)(bp) - DSIZE))) /* 前一个块的指针 */ -// 计算下一个和前一个块的地址 -#define NEXT_BLKP(bp) ((char *)(bp) + GET_SIZE(((char *)(bp) - WSIZE))) -#define PREV_BLKP(bp) ((char *)(bp) - GET_SIZE(((char *)(bp) - DSIZE))) - -static char *heap_listp; // 指向堆的起始位置 +static char *heap_listp; /* 指向堆的第一个块的指针 */ static void *extend_heap(size_t words); static void *coalesce(void *bp); @@ -80,8 +80,9 @@ static void place(void *bp, size_t asize); static void print_block(int request_id, int payload); /* - * mm_init - - * 初始化malloc系统,此函数,在整个运行期间,只被调用1次,用于建立初始化环境 + * mm_init - 初始化内存分配器 + * 创建初始空堆,包括序言块和结尾块 + * 返回值:成功返回0,错误返回-1 */ int mm_init(void) { // 创建初始空堆 @@ -99,6 +100,11 @@ int mm_init(void) { return 0; } +/* + * extend_heap - 通过增加brk指针来扩展堆 + * 参数 words: 请求的字数(以字为单位) + * 返回值:指向新分配区域的指针,如果出错则返回NULL + */ static void *extend_heap(size_t words) { char *bp; size_t size; @@ -116,6 +122,17 @@ static void *extend_heap(size_t words) { return coalesce(bp); } +/* + * coalesce - 合并相邻的空闲块 + * 参数 bp: 指向刚被释放的块的指针 + * 返回值:指向合并后的块的指针 + * + * 有四种情况: + * Case 1:前后块都已分配 + * Case 2:前块已分配,后块空闲 + * Case 3:前块空闲,后块已分配 + * Case 4:前后块都空闲 + */ static void *coalesce(void *bp) { size_t prev_alloc = GET_ALLOC(FTRP(PREV_BLKP(bp))); size_t next_alloc = GET_ALLOC(HDRP(NEXT_BLKP(bp))); @@ -141,6 +158,16 @@ static void *coalesce(void *bp) { return bp; } +/* + * mm_malloc - 分配一个大小为size字节的块 + * 参数 size: 请求的字节数 + * 返回值:指向新分配块的指针,如果错误则返回NULL + * + * 分配策略: + * 1. 调整请求大小为8字节对齐 + * 2. 搜索空闲链表找到第一个适合的块 + * 3. 如果没有找到合适的块,扩展堆 + */ void *mm_malloc(size_t size) { size_t asize; // 调整后的块大小 size_t extendsize; // 如果没有合适的块,扩展堆的大小 @@ -166,6 +193,14 @@ void *mm_malloc(size_t size) { return bp; } +/* + * mm_free - 释放一个之前分配的块 + * 参数 bp: 指向要释放的块的指针 + * + * 处理步骤: + * 1. 标记块为空闲(更新头部和脚部) + * 2. 合并相邻的空闲块(如果有的话) + */ void mm_free(void *bp) { if (bp == NULL) return; @@ -176,6 +211,18 @@ void mm_free(void *bp) { coalesce(bp); } +/* + * mm_realloc - 调整一个已分配块的大小 + * 参数: + * ptr - 指向旧块的指针 + * size - 请求的新大小 + * 返回值:指向新块的指针 + * + * 处理策略: + * 1. 如果ptr为NULL,等同于malloc + * 2. 如果size为0,等同于free + * 3. 分配新块,复制数据,释放旧块 + */ void *mm_realloc(void *ptr, size_t size) { if (ptr == NULL) return mm_malloc(size); @@ -197,6 +244,11 @@ void *mm_realloc(void *ptr, size_t size) { return newptr; } +/* + * find_fit - 使用首次适配搜索,查找满足所需大小的空闲块 + * 参数 asize: 调整后的块大小 + * 返回值:找到则返回块指针,否则返回NULL + */ static void *find_fit(size_t asize) { void *bp; @@ -208,6 +260,14 @@ static void *find_fit(size_t asize) { return NULL; } +/* + * place - 将请求的块放置在空闲块的起始位置 + * 参数: + * bp - 空闲块指针 + * asize - 请求的大小 + * + * 如果剩余部分足够大(>= 2*DSIZE),则分割块 + */ static void place(void *bp, size_t asize) { size_t csize = GET_SIZE(HDRP(bp));