前言
这个实验想法还是十分清晰的,但是我写了几次都直接错误了,然后bug也不知道到底是哪里出现了问题,最后就只好参考别人的了。
参考博客:实验5:malloc lab
代码
#include "mm.h"
#include "memlib.h"
team_t team = {
/* Team name */
"XXXXXX",
/* First member's full name */
"yzf",
/* First member's email address */
"@Fd",
/* Second member's full name (leave blank if none) */
"",
/* Second member's email address (leave blank if none) */
""
};
#define ALIGNMENT 8
/* rounds up to the nearest multiple of ALIGNMENT */
#define ALIGN(size) (((size) + (ALIGNMENT-1)) & ~0x7)
#define SIZE_T_SIZE (ALIGN(sizeof(size_t)))
#define WSIZE 4
#define DSIZE 8
#define CHUNKSIZE (1<<12) /* Extend heap by this amount (bytes) */
#define MINBLOCKSIZE 16
#define MAX(x, y) ((x) > (y) ? (x) : (y))
#define PACK(size, alloc) ((size) | (alloc)) /* Pack a size and allocated bit into a word */
#define GET(p) (*(unsigned int *)(p)) /* read a word at address p */
#define PUT(p, val) (*(unsigned int *)(p) = (val)) /* write a word at address p */
#define GET_SIZE(p) (GET(p) & ~0x7) /* read the size field from address p */
#define GET_ALLOC(p) (GET(p) & 0x1) /* read the alloc field from address p */
#define HDRP(bp) ((char*)(bp) - WSIZE) /* given block ptr bp, compute address of its header */
#define FTRP(bp) ((char*)(bp) + GET_SIZE(HDRP(bp)) - DSIZE) /* given block ptr bp, compute address of its footer */
#define NEXT_BLKP(bp) ((char*)(bp) + GET_SIZE(HDRP(bp))) /* given block ptr bp, compute address of next blocks */
#define PREV_BLKP(bp) ((char*)(bp) - GET_SIZE((char*)(bp)-DSIZE)) /* given block ptr bp, compute address of prev blocks */
static char* heap_listp;
static void* extend_heap(size_t size);
static void* coalesce(void *bp);
static void* find_fit(size_t asize);
static void split_block(void* bp, size_t asize);
static void place(void* bp, size_t asize);
int mm_init(void);
void *mm_malloc(size_t size);
void mm_free(void *bp);
void *mm_realloc(void *ptr, size_t size);
/*
* extend heap by words * word(4 bytes)
*/
static void* extend_heap(size_t words)
{
char* bp;
size_t size;
/* Allocate an even number of words to maintain alignment */
size = (words % 2) ? (words + 1) * WSIZE : words * WSIZE;
if ((long)(bp = mem_sbrk(size)) == -1)
return NULL;
/* Initialize free block header/footer and the epilogue header */
PUT(HDRP(bp), PACK(size, 0)); //free block header
PUT(FTRP(bp), PACK(size, 0)); //free block footer
PUT(HDRP(NEXT_BLKP(bp)), PACK(0, 1)); // new epilogue header
return coalesce(bp); //coalesce if the previous block was free
}
/*
* coalesce
*/
static void* coalesce(void *bp)
{
size_t pre_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(pre_alloc&&next_alloc)return bp;
else if(!pre_alloc&&next_alloc){
size+=GET_SIZE(FTRP(PREV_BLKP(bp)));
PUT(HDRP(PREV_BLKP(bp)),PACK(size,0));
PUT(FTRP(bp),PACK(size,0));
return PREV_BLKP(bp);
}else if(pre_alloc&&!next_alloc){
size+=GET_SIZE(HDRP(NEXT_BLKP(bp)));
PUT(HDRP(bp),PACK(size,0));
PUT(FTRP(bp),PACK(size,0));
return bp;
}else {
size+=GET_SIZE(FTRP(PREV_BLKP(bp)))+GET_SIZE(HDRP(NEXT_BLKP(bp)));
PUT(HDRP(PREV_BLKP(bp)),PACK(size,0));
PUT(FTRP(PREV_BLKP(bp)),PACK(size,0));
return PREV_BLKP(bp);
}
}
/*
* find_fit - use first fit strategy to find an empty block.
*/
static void* find_fit(size_t asize)
{
char*listp;
for(listp=heap_listp;GET_SIZE(HDRP(listp));listp=NEXT_BLKP(listp)){
size_t alloc=GET_ALLOC(HDRP(listp));
size_t size=GET_SIZE(HDRP(listp));
if(!alloc&&asize<=size){
return listp;
}
}
return NULL;
}
/*
* split_block
*/
static void split_block(void* bp, size_t asize)
{
size_t size = GET_SIZE(HDRP(bp));
if ((size - asize) >= MINBLOCKSIZE)
{
PUT(HDRP(bp), PACK(asize, 1));
PUT(FTRP(bp), PACK(asize, 1));
bp = NEXT_BLKP(bp);
PUT(HDRP(bp), PACK(size-asize, 0));
PUT(FTRP(bp), PACK(size-asize, 0));
}
}
/*
* place - Place the request block at the beginning of the free block,
* and only split if the remaining part is equal to or larger than the size of the smallest block
*/
static void place(void* bp, size_t asize)
{
size_t size = GET_SIZE(HDRP(bp));
PUT(HDRP(bp), PACK(size, 1));
PUT(FTRP(bp), PACK(size, 1));
split_block(bp, asize);
}
/*
* mm_init - initialize the malloc package.
*/
int mm_init(void)
{
size_t *bp;
if((bp=mem_sbrk(4*WSIZE))==(void*)-1){
return -1;
}
PUT(heap_listp,0);
PUT(heap_listp+WSIZE,PACK(DSIZE,1));
PUT(heap_listp+2*WSIZE,PACK(DSIZE,1));
PUT(heap_listp+3*WSIZE,PACK(0,1));
heap_listp+=2*WSIZE;
next_listp=heap_listp;
if((bp=extend_heap(CHUNKSIZE/WSIZE))==NULL)return -1;
return 0;
}
/*
* mm_malloc - Allocate a block by incrementing the brk pointer.
* Always allocate a block whose size is a multiple of the alignment.
*/
void *mm_malloc(size_t size)
{
size_t *bp;
size_t asize,extendsize;
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;
}
/*
* mm_free - Freeing a block does nothing.
*/
void mm_free(void *bp)
{
size_t size = GET_SIZE(HDRP(bp));
PUT(HDRP(bp), PACK(size, 0));
PUT(FTRP(bp), PACK(size, 0));
coalesce(bp);
}
/*
* mm_realloc - Implemented simply in terms of mm_malloc and mm_free
*/
void *mm_realloc(void *ptr, size_t size)
{
void *oldptr = ptr;
void *newptr;
size_t copySize;
newptr = mm_malloc(size);
if (newptr == NULL)
return NULL;
size = GET_SIZE(HDRP(oldptr));
copySize = GET_SIZE(HDRP(newptr));
if (size < copySize)
copySize = size;
memcpy(newptr, oldptr, copySize-WSIZE);
mm_free(oldptr);
return newptr;
}