Skip to content

Latest commit

 

History

History
500 lines (451 loc) · 14.6 KB

CSAPP之详解MollocLab.md

File metadata and controls

500 lines (451 loc) · 14.6 KB

实验材料与规则

官网的实习手册是缺了测试材料的,所以我建议你直接从这里下载吧: https://github.com/happysnaker/CSAPPLabs/tree/CSAPP/molloc-Lab

实验仅要求我们修改mm.c文件,要求完成init, molloc, free, recalloc 四个函数,其中部分与系统接口的函数已在memlib.c文件中给出。

完成之后,我们需要键入以下三条命令来跑分:

make clean
make mdriver
./mdriver

这个实验难度特别大,其中非常容易碰到段错误,以至于我最后一个分离式的链表仍然没有实现,实乃一个遗憾。立个flag,2021年一定要实现它!

实验部分

隐式空闲链表加首次适配

首次适配从头遍历链表,找到空闲块。这个跑分不是很理想,甚至还不及格,只有56分。这个就是书上的思路,其中要自己完善两个函数。 代码:隐式空闲链表加首次适配实现

隐式空闲链表加下一次次适配

下一次适配从上次操作的时候开始遍历。这种方式竟然出奇的理想,跑了82分:

/*
Team Name:happysnaker
Member 1 :qwewqewqqe:qwewqewqqe
Using default tracefiles in traces/
Perf index = 42 (util) + 40 (thru) = 82/100
*/

我们留下一个bookstr来表示上一次操作时的指针,由于我们每一次释放空闲块都让这个指针指向了空闲块,所以下一次分配时速度非常块,可以看到效率部分拿了满分(40),但利用率却不理想。

代码:

/*
Team Name:happysnaker
Member 1 :qwewqewqqe:qwewqewqqe
Using default tracefiles in traces/
Perf index = 42 (util) + 40 (thru) = 82/100
*/
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <unistd.h>
#include <string.h>
#include "mm.h"
#include "memlib.h"
team_t team = {
    /* Team name */
    "ateam",
    /* First member's full name */
    "Harry Bovik",
    /* First member's email address */
    "[email protected]",
    /* Second member's full name (leave blank if none) */
    "",
    /* Second member's email address (leave blank if none) */
    ""
};

/* single word (4) or double word (8) alignment */
#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)
#define MAX(X, Y) ((X) > (Y) ? (X) : (Y))
#define PACK(size, alloc) ((size) | (alloc))  /*设置头部或脚部*/
#define GET(p) (*(unsigned int*)(p))
#define PUT(p, val) (*(unsigned int*)(p) = (val))
#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 void* extend_heap(size_t words);
static void* coalesce(void* bp);
static void *find_fit(size_t size);
static void place(void *bp,size_t asize);
static char *heap_listp = 0;
static void* bookptr;
/* 
 * mm_init - initialize the malloc package.
 */
int mm_init(void)
{
    if ((heap_listp = mem_sbrk(4 * WSIZE)) == (void*)-1)
	    return -1;
    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);
    bookptr = (unsigned int)heap_listp + DSIZE;  /*初始化*/
    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));
	bookptr = coalesce(bp);  /*让它指向空闲指针*/
	return bookptr;
}

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)
		return bp;
	else if (prev_alloc && !next_alloc){
		size += GET_SIZE(HDRP(NEXT_BLKP(bp)));
		PUT(FTRP(NEXT_BLKP(bp)), PACK(size, 0));
		PUT(HDRP(bp), PACK(size, 0));
	}
	else if (!prev_alloc && next_alloc){
		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{
		size += GET_SIZE(HDRP(PREV_BLKP(bp))) + GET_SIZE(HDRP(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;
}
/* 
 * 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)
{
	char *bp;
        size_t asize;
	size_t 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);
		bookptr = bp;
		return bp;
	}
	extendsize = MAX(asize, CHUNKSIZE);
	if ((bp = extend_heap(extendsize / WSIZE)) == NULL)
		return NULL;
	place(bp, asize);
	bookptr = bp;  /*指向上一个分配的块*/
	return bp;
}

/*
 * mm_free - Freeing a block does nothing.
 */
void mm_free(void *ptr)
{
	size_t size = GET_SIZE(HDRP(ptr));
	PUT(HDRP(ptr), PACK(size, 0));
	PUT(FTRP(ptr), PACK(size, 0));
	bookptr = coalesce(ptr);  /*指向空闲块*/
	return;
}

/*
 * mm_realloc - Implemented simply in terms of mm_malloc and mm_free
 */

static void *find_fit(size_t size){
    while (GET_SIZE(HDRP(bookptr)) > 0){
		if (GET_SIZE(HDRP(bookptr)) >= size && GET_ALLOC(HDRP(bookptr)) == 0)
			return bookptr;
		bookptr = NEXT_BLKP(bookptr); /*别忘了更新它*/
	}
    return NULL;
}
static void place(void *bp,size_t asize){
   size_t nowsize = GET_SIZE(HDRP(bp));
	if (nowsize - asize < 2 * DSIZE){
		PUT(HDRP(bp), PACK(nowsize, 1));
		PUT(FTRP(bp), PACK(nowsize, 1));
	}
	else{
		PUT(HDRP(bp), PACK(asize, 1));
		PUT(FTRP(bp), PACK(asize, 1));
		PUT(HDRP(NEXT_BLKP(bp)), PACK(nowsize - asize, 0));
		PUT(FTRP(NEXT_BLKP(bp)), PACK(nowsize - asize, 0));
	}
	return;
}
/*
 * mm_realloc - Implemented simply in terms of mm_malloc and mm_free
 */
void *mm_realloc(void *ptr, size_t size)
{
    size_t oldsize = GET_SIZE(HDRP(ptr));
	void* newptr = mm_malloc(size);
	if (!newptr)
		return 0;
	bookptr = newptr;  /*指向空闲块*/
	if (!ptr)
		return newptr;
	memcpy(newptr, ptr, (size < oldsize ? size : oldsize));
	mm_free(ptr);
	return newptr;
}

隐式空闲链表加最佳适配

找到最小适合的块,提高利用率,这个跑分不是很理想,只有56分。代码: 隐式空闲链表加最佳适配

显式空闲链表加FIFO

这一次采用双向链表,块的大小至少需要16字节,当前块指针bp指向的四字节保存着上一空闲块的指针,bp + 4保存着下一空闲块的指针。当我们有空闲块时,我们简单的插入到根节点处。

/*
Team Name:happysnaker
Member 1 :qwewqewqqe:qwewqewqqe
Using default tracefiles in traces/
Perf index = 45 (util) + 40 (thru) = 85/100
*/

代码:

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <unistd.h>
#include <string.h>
#include "mm.h"
#include "memlib.h"

/*********************************************************
 * NOTE TO STUDENTS: Before you do anything else, please
 * provide your team information in the following struct.
 ********************************************************/
team_t team =
{
    /* Team name */
    "Xwqe",
    /* First member's full name */
    "qewqe",
    /* First member's email address */
    "sadsa",
    /* Second member's full name (leave blank if none) */
    "",
    /* Second member's email address (leave blank if none) */
    ""
};

/* single word (4) or double word (8) alignment */
#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           /*Double word size*/
#define CHUNKSIZE    (1<<12) /*the page size in bytes is 4K*/
#define MAX(x,y)     ((x)>(y)?(x):(y))
#define PACK(size,alloc)    ((size) | (alloc))
#define GET(p)       (*(unsigned int *)(p))
#define PUT(p,val)   (*(unsigned int *)(p) = (val))
#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 PREV_BLKP(bp)   ((char *)(bp)-GET_SIZE(((char *)(bp)-DSIZE)))
#define NEXT_BLKP(bp)   ((char *)(bp)+GET_SIZE(((char *)(bp)-WSIZE)))
#define NEXT_RP(bp)  ((unsigned int)(bp)+WSIZE) /*指向下一空闲块指针*/

int mm_check(char *function);
static void *extend_heap(size_t dwords);
static void *coalesce(void *bp);
static void *find_fit(size_t size);
static void place(void *bp,size_t asize);
void __insert(char *p);
void __remove(char *p);
static char *heap_listp = NULL;
static char *root = NULL; /*这是我们的根节点*/

/*
 * mm_init - initialize the malloc package.
 * The return value should be -1 if there was a problem in performing the initialization, 0 otherwise
 */
int mm_init(void){
    if((heap_listp = mem_sbrk(6*WSIZE))==(void *)-1) return -1;
    PUT(heap_listp,0);
    PUT(heap_listp+(1*WSIZE),0);
    PUT(heap_listp+(2*WSIZE),0); /*内存对齐*/
    PUT(heap_listp+(3*WSIZE),PACK(DSIZE,1));
    PUT(heap_listp+(4*WSIZE),PACK(DSIZE,1)); /*内存对齐*/
    PUT(heap_listp+(5*WSIZE),PACK(0,1)); /*尾巴*/
    root = heap_listp + (1*WSIZE);/*初始化根节点*/
    heap_listp += (4*WSIZE);
    if((extend_heap(CHUNKSIZE/DSIZE)) == 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 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/DSIZE))==NULL)
        return NULL;
    place(bp,asize);
    return bp;
}

/*
 * mm_free - Freeing a block does nothing.
 */
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));
    PUT(NEXT_RP(bp),0); /*刚释放的块,设置前后指针为null*/
    PUT(bp,0);
    coalesce(bp);
}
/*
 * mm_realloc - Implemented simply in terms of mm_malloc and mm_free
 */
void *mm_realloc(void *ptr, size_t size){
    
    void *newptr = mm_malloc(size);
	if(!newptr){
        return 0;
    }
    if(ptr == NULL){
        return newptr;
    }

    size_t oldsize = GET_SIZE(HDRP(ptr));
    memcpy(newptr, ptr, oldsize < size ? oldsize : size);
    mm_free(ptr);

    return newptr;
}
static void *find_fit(size_t size){
    /*first fit*/
    char *bp = GET(root);
    while(bp != NULL){
        if(GET_SIZE(HDRP(bp)) >= size) 
			return bp;	
        bp = GET(NEXT_RP(bp));
    }
    return NULL;

}

static void place(void *bp,size_t asize)
{
    size_t csize = GET_SIZE(HDRP(bp));
	__remove(bp);   /*使用了这个块,切记移除它*/
    if(csize-asize >= 2 *DSIZE){
        PUT(HDRP(bp),PACK(asize,1));
        PUT(FTRP(bp),PACK(asize,1));
        PUT(HDRP(NEXT_BLKP(bp)),PACK(csize-asize,0));
        PUT(FTRP(NEXT_BLKP(bp)),PACK(csize-asize,0));
        PUT(NEXT_RP(bp),0);
        PUT((NEXT_BLKP(bp)),0);
        coalesce(NEXT_BLKP(bp));
    }
    else{
        PUT(HDRP(bp),PACK(csize,1));
        PUT(FTRP(bp),PACK(csize,1));
    }
}

static void *extend_heap(size_t words)
{
    char *bp;
    size_t size;
    size = (words % 2) ? (words+1) * DSIZE : words * DSIZE;
    if((long)(bp = mem_sbrk(size))==(void *)-1)
        return NULL;
    PUT(HDRP(bp),PACK(size,0));
    PUT(FTRP(bp),PACK(size,0));
    PUT(HDRP(NEXT_BLKP(bp)),PACK(0,1));
    PUT(NEXT_RP(bp),0);
    PUT(bp,0);
    return coalesce(bp);
}

/*coalesce the empty block*/
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));

    /*coalesce the block and change the point*/
    if(prev_alloc && !next_alloc){
        size += GET_SIZE(HDRP(NEXT_BLKP(bp)));
        __remove(NEXT_BLKP(bp)); /*使用了这个块,切记移除它*/
        PUT(HDRP(bp), PACK(size,0));
        PUT(FTRP(bp), PACK(size,0));
    }
    else if(!prev_alloc && next_alloc){
        size += GET_SIZE(HDRP(PREV_BLKP(bp)));
        __remove(PREV_BLKP(bp));/*使用了这个块,切记移除它*/
        PUT(FTRP(bp),PACK(size,0));
        PUT(HDRP(PREV_BLKP(bp)),PACK(size,0));
        bp = PREV_BLKP(bp);
    }
    else if (!prev_alloc && !next_alloc){
        size +=GET_SIZE(FTRP(NEXT_BLKP(bp)))+ GET_SIZE(HDRP(PREV_BLKP(bp)));
        __remove(PREV_BLKP(bp));/*使用了这个块,切记移除它*/
        __remove(NEXT_BLKP(bp));/*使用了这个块,切记移除它*/
        PUT(FTRP(NEXT_BLKP(bp)),PACK(size,0));
        PUT(HDRP(PREV_BLKP(bp)),PACK(size,0));
        bp = PREV_BLKP(bp);
    }
    __insert(bp);/*新的空闲块,记住插入*/
    return bp;
}
inline void __insert(char *bp)
{
    //PUT(bp, root); 这个操作有段错误,挺离谱的
    char *next = GET(root);
    if(next != NULL)
        PUT(next, bp);
    PUT(NEXT_RP(bp), next);
    PUT(root,bp);
}
inline void __remove(char *bp){
    char *pre = GET((bp));
    char *next = GET(NEXT_RP(bp));
    /*因为上面插入操作不能置bp的前驱为root,所以这个是必须考虑的,这个代表前面就是根节点了 */
    if(pre == NULL){
        if(next != NULL)
			PUT(next,0);
        PUT(root,next);
    }
    else{
        if(next != NULL)
			PUT((next),pre);
        PUT(NEXT_RP(pre),next);
    }
    PUT(NEXT_RP(bp),0);
    PUT(bp,0);
}


插入操作设置前驱为root竟然有段错误,真是折杀我也,也许是因为不经意间会访问NEXT_RP(root)吧,这个值被我们设置成了NULL。哎,由衷敬佩操作系统开发者,和内存打交道太不容易了。

其实这个在插入时我觉得还可以以升序的方式插入,这样可以提高利用率。可惜了,还是我们的老朋友段错误,哎。

看来想要满绩(90)必须要采用分离适配了,最近被段错误弄的有点晕,不过立个flag,2021年一定要完成它!