CSAPP之详解MollocLab

实验材料与规则

官网的实习手册是缺了测试材料的,所以我建议你直接从这里下载吧:
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 */
    "bovik@cs.cmu.edu",
    /* 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年一定要完成它!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,640评论 6 507
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,254评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,011评论 0 355
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,755评论 1 294
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,774评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,610评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,352评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,257评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,717评论 1 315
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,894评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,021评论 1 350
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,735评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,354评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,936评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,054评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,224评论 3 371
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,974评论 2 355

推荐阅读更多精彩内容