Files
csapp2025/malloclab/mm.c
2025-05-26 19:19:19 +08:00

238 lines
6.7 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#define MAX(x, y) ((x) > (y) ? (x) : (y))
/*
* mm-naive.c - 参考实现是一个最快的、最低效率的malloc.
*
* 在这个参考实现中分配一个块仅仅是增加brk指针
* 块内部全部是载荷数据块内没有header或者footer等
* 管理用的数据信息。分配出去的块,永远不释放或者回收。
* 重分配函数realloc的实现是直接通过mm_malloc和mm_free实现的
*
* 亲们请注意:你需要把此段注释,替换成你的算法设计思想。用描述性
* 的话来说清楚。
* 请将此文件重新命名为mm_201309060024.c就是mm_你的学号.c
*/
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#ifndef _WIN32
#include <unistd.h>
#endif
#include <string.h>
#include "memlib.h"
#include "mm.h"
/*********************************************************
* 亲们请注意:开始之前,请把下面的信息修改为你的个人信息
********************************************************/
team_t team = {
/* 团队名字 */
"Tom is a Cat",
/* 团队老大的名字 */
"Tom",
/* 团队老大的email地址 */
"Tom@sina.com",
/* 团队其他成员的名字 (如果没有,就空着) */
"",
/* 团队其他成员的email地址 (如果没有,就空着) */
""};
/* 单字 (4) 还是双字 (8) 边界对齐 */
#define ALIGNMENT 8
/* 舍入到最近的ALIGNMENT边界上 */
#define ALIGN(size) (((size) + (ALIGNMENT - 1)) & ~0x7)
#define SIZE_T_SIZE (ALIGN(sizeof(size_t)))
// 定义块头部和尾部的大小
#define WSIZE 4 // 字大小4字节
#define DSIZE 8 // 双字大小8字节
#define CHUNKSIZE (1 << 12) // 扩展堆的默认大小4KB
// 将大小和分配位打包成一个字
#define PACK(size, alloc) ((size) | (alloc))
// 读取和写入地址p处的字
#define GET(p) (*(unsigned int *)(p))
#define PUT(p, val) (*(unsigned int *)(p) = (val))
// 从地址p读取大小和分配位
#define GET_SIZE(p) (GET(p) & ~0x7)
#define GET_ALLOC(p) (GET(p) & 0x1)
// 计算块的头部和尾部地址
#define HDRP(bp) ((char *)(bp) - WSIZE)
#define FTRP(bp) ((char *)(bp) + GET_SIZE(HDRP(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 void *extend_heap(size_t words);
static void *coalesce(void *bp);
static void *find_fit(size_t asize);
static void place(void *bp, size_t asize);
static void print_block(int request_id, int payload);
/*
* mm_init -
* 初始化malloc系统此函数在整个运行期间只被调用1次用于建立初始化环境
*/
int mm_init(void) {
// 创建初始空堆
if ((heap_listp = mem_sbrk(4 * WSIZE)) == (void *)-1)
return -1;
PUT(heap_listp, 0); // 对齐填充
PUT(heap_listp + (1 * WSIZE), PACK(DSIZE, 1)); // 序言块头部
PUT(heap_listp + (2 * WSIZE), PACK(DSIZE, 1)); // 序言块尾部
PUT(heap_listp + (3 * WSIZE), PACK(0, 1)); // 结尾块
heap_listp += (2 * WSIZE);
// 扩展空堆
if (extend_heap(CHUNKSIZE / WSIZE) == NULL)
return -1;
return 0;
}
static void *extend_heap(size_t words) {
char *bp;
size_t size;
// 分配偶数个字以保持对齐
size = (words % 2) ? (words + 1) * WSIZE : words * WSIZE;
if ((long)(bp = mem_sbrk(size)) == -1)
return NULL;
// 初始化空闲块头部/尾部和结尾块
PUT(HDRP(bp), PACK(size, 0)); // 空闲块头部
PUT(FTRP(bp), PACK(size, 0)); // 空闲块尾部
PUT(HDRP(NEXT_BLKP(bp)), PACK(0, 1)); // 新的结尾块
return coalesce(bp);
}
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)));
size_t size = GET_SIZE(HDRP(bp));
if (prev_alloc && next_alloc) { // Case 1
return bp;
} else if (prev_alloc && !next_alloc) { // Case 2
size += GET_SIZE(HDRP(NEXT_BLKP(bp)));
PUT(HDRP(bp), PACK(size, 0));
PUT(FTRP(bp), PACK(size, 0));
} else if (!prev_alloc && next_alloc) { // Case 3
size += GET_SIZE(HDRP(PREV_BLKP(bp)));
PUT(FTRP(bp), PACK(size, 0));
PUT(HDRP(PREV_BLKP(bp)), PACK(size, 0));
bp = PREV_BLKP(bp);
} else { // Case 4
size += GET_SIZE(HDRP(PREV_BLKP(bp))) + GET_SIZE(FTRP(NEXT_BLKP(bp)));
PUT(HDRP(PREV_BLKP(bp)), PACK(size, 0));
PUT(FTRP(NEXT_BLKP(bp)), PACK(size, 0));
bp = PREV_BLKP(bp);
}
return bp;
}
void *mm_malloc(size_t size) {
size_t asize; // 调整后的块大小
size_t extendsize; // 如果没有合适的块,扩展堆的大小
char *bp;
if (size == 0)
return NULL;
if (size <= DSIZE)
asize = 2 * DSIZE;
else
asize = DSIZE * ((size + (DSIZE) + (DSIZE - 1)) / DSIZE);
if ((bp = find_fit(asize)) != NULL) {
place(bp, asize);
return bp;
}
extendsize = MAX(asize, CHUNKSIZE);
if ((bp = extend_heap(extendsize / WSIZE)) == NULL)
return NULL;
place(bp, asize);
return bp;
}
void mm_free(void *bp) {
if (bp == NULL)
return;
size_t size = GET_SIZE(HDRP(bp));
PUT(HDRP(bp), PACK(size, 0));
PUT(FTRP(bp), PACK(size, 0));
coalesce(bp);
}
void *mm_realloc(void *ptr, size_t size) {
if (ptr == NULL)
return mm_malloc(size);
if (size == 0) {
mm_free(ptr);
return NULL;
}
void *newptr = mm_malloc(size);
if (newptr == NULL)
return NULL;
size_t copySize = GET_SIZE(HDRP(ptr)) - DSIZE;
if (size < copySize)
copySize = size;
memcpy(newptr, ptr, copySize);
mm_free(ptr);
return newptr;
}
static void *find_fit(size_t asize) {
void *bp;
for (bp = heap_listp; GET_SIZE(HDRP(bp)) > 0; bp = NEXT_BLKP(bp)) {
if (!GET_ALLOC(HDRP(bp)) && (asize <= GET_SIZE(HDRP(bp)))) {
return bp;
}
}
return NULL;
}
static void place(void *bp, size_t asize) {
size_t csize = GET_SIZE(HDRP(bp));
if ((csize - asize) >= (2 * DSIZE)) {
PUT(HDRP(bp), PACK(asize, 1));
PUT(FTRP(bp), PACK(asize, 1));
bp = NEXT_BLKP(bp);
PUT(HDRP(bp), PACK(csize - asize, 0));
PUT(FTRP(bp), PACK(csize - asize, 0));
} else {
PUT(HDRP(bp), PACK(csize, 1));
PUT(FTRP(bp), PACK(csize, 1));
}
}
/*
* mm_heapcheck - 目前暂不支持堆检查,可以不用修改
*/
void mm_heapcheck(void) {}
/*
* 输出一块数据 - 用于heapcheck然而在此并没有什么用可以不用修改
*/
static void print_block(int request_id, int payload) {
printf("\n[%s]$BLOCK %d %d\n", __func__, request_id, payload);
}