CSAPP:malloclab

#CSAPP:malloclab
CSAPP:9.9.12
针对空闲块的组织方法有以下三种:

  • a.隐式空闲链表(implicit free list)
  • b.显式空闲链表(explicit free list)
  • c.分离空闲链表(segregated free list)

查找空闲块的三个方法:

  • a.首次适应(first fit)
  • b.最佳适配(best fit)
  • c.下一次适配(next fit)
  • d.分离适配,特殊情况包括伙伴系统,优点在于快速搜索和快速合并(大小相同,地址连续)。

方案一:隐式空闲链表+first fit/next fit

  1. 初始化堆 —— mm_init函数
    mm_init步骤如下:

首先在堆上分配16个字节,包括4字节对齐块,8字节序言块,4字节结尾块。

调extend_heap扩展堆,创建初始的空闲块,大小为4096字节。

  1. 扩展堆 —— extend_heap函数
    函数原型: static void *extend_heap(size_t words);

以下两种场景需要扩展堆:

调用mm_init初始化堆时。
调用mm_malloc找不到合适的空闲块时。

  1. 释放和合并块 —— mm_free和coalesce函数

调用mm_free释放块,步骤如下:
将当前块的头部和脚部中的分配位清零。
将这个块与它邻接的前后空闲块进行合并,采用立即合并策略。

调用coalesce合并前后的合并块,原型:static void *coalesce(void *bp);,分四种情况:

情况1:前面的块和后面的块都已分配 —— 不可能合并,简单返回bp即可。
情况2:前面的块已分配,后面的块空闲 —— 用当前块和后面块的大小之和更新当前块的头部和后面块的脚部。返回bp
情况3:前面的块是空闲的,后面的块是分配的 —— 用两块大小之和更新前面块的头部和后面块的脚部。返回PREV_BLKP(bp)
情况4:前面和后面的块都是空闲的 —— 用三个块大小之和更新前面块的头部和后面块的脚部。返回PREV_BLKP(bp)

https://blog.csdn.net/pcj_888/article/details/108812886

#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 */
    "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) */
    ""
};

static char *heap_listp; 

#define WSIZE 4     /* Word and header/footer size (bytes) */
#define DSIZE 8     /* Double word size (bytes) */
#define CHUNKSIZE (1<<12)   /* Extend heap by this amount (bytes) */
 
#define MAX(x, y) ((x) > (y) ? (x) : (y))
 
/* Pack a size and allocated bit into  word */
#define PACK(size, alloc) ((size) | (alloc))
 
/* Read and write a word at address p */
#define GET(p) (*(unsigned int *)(p))
#define PUT(p, val) (*(unsigned int *)(p) = (val))
 
/* Read the size and allocated fields from address p */
#define GET_SIZE(p) (GET(p) & ~0x7)
#define GET_ALLOC(p) (GET(p) & 0x1)// 判断这个块是否已分配

/* Given block ptr bp, compute address of its header and footer */
#define HDRP(bp) ((char *)(bp) - WSIZE)
#define FTRP(bp) ((char *)(bp) + GET_SIZE(HDRP(bp)) - DSIZE)
 
/* Given block ptr bp, compute address of next and previous blocks */
#define NEXT_BLKP(bp) ((char *)(bp) + GET_SIZE(((char *)(bp) - WSIZE)))
#define PREV_BLKP(bp) ((char *)(bp) - GET_SIZE(((char *)(bp) - DSIZE)))
 
 /* Globe var */
static char *heap_listp;
 
/* 函数声明 */
static void *extend_heap(size_t words);
static void *coalesce(void *bp);
static void *find_fit(size_t asize);

/* 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)))


/* 
 * mm_init - initialize the malloc package.
 */
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);
}

void place(void *bp,size_t asize){
    size_t csize=GET_SIZE(HDRP(bp));
//若剩下的空间比2*DSIZE占的空间大,那么就分割它
    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_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/WSIZE))==NULL)
        return NULL;
    place(bp,asize);
    return bp;
}
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)))){
       //寻找第一个可以匹配的块
       //heap_listp = bp;  //next_fit,每次让它指向最后分配的位置就好,下次从这里匹配
        return bp;
       }
   }
 
    return NULL;
}
 

/*
 * 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);
}

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(HDRP(bp),PACK(size,0));
	PUT(FTRP(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(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;

}

/*
 * 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;
    copySize = *(size_t *)((char *)oldptr - SIZE_T_SIZE);
    if (size < copySize)
      copySize = size;
    memcpy(newptr, oldptr, copySize);
    mm_free(oldptr);
    return newptr;
}



  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值