0x00 Overview
可以看一下要求:http://csapp.cs.cmu.edu/3e/malloclab.pdf
0x01 组织模式
隐式空闲链表
隐式空闲链表的结构:
隐式空闲链表利用空闲块头部的标志位将空闲块间接的连接起来。
遍历整个堆时,遇到已经分配块自动跳过,根据空闲部头部的size来寻找空闲块。
0x02 隐式空闲链表
mm_init
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| 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; }
|
mem_sbrk函数,有一点要注意一下,mem_brk永远指向堆的最后一个字节。
1 2 3 4 5 6 7 8 9 10 11 12
| void *mem_sbrk(int incr) { char *old_brk = mem_brk;
if ( (incr < 0) || ((mem_brk + incr) > mem_max_addr)) { errno = ENOMEM; fprintf(stderr, "ERROR: mem_sbrk failed. Ran out of memory...\n"); return (void *)-1; } mem_brk += incr; return (void *)old_brk; }
|
extend_heap
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| 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); }
|
当堆被初始化时调用extend_heap函数时的情形
- 调用完mem_sbrk
运行完 PUT(HDRP(bp),PACK(size,0));
将结尾块变成起始块,赋值上size和alloc。
PUT(FTRP(bp),PACK(size,0));
将size-8的位置设置上footer,因为把header和footer都算进size里了。
PUT(HDRP(NEXT_BLKP(bp)),PACK(0,1));
将最后一个字变成结尾块
宏定义
如果前面的看懂了,那就可以理解所有的宏定义了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| #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)))
|
coalesce
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| 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_free
1 2 3 4 5 6 7 8 9
| 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_malloc
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| 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; }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| static void *find_fit(size_t asize) { void *bp = heap_listp; size_t size; while((size = GET_SIZE(HDRP(bp))) != 0){ if(size >= asize && !GET_ALLOC(HDRP(bp))) return bp; bp = NEXT_BLKP(bp); } return NULL; } static void place(void *bp, size_t asize) { size_t remain_size; remain_size = GET_SIZE(HDRP(bp)) - asize; if(remain_size >= DSIZE){ PUT(HDRP(bp), PACK(asize, 1)); PUT(FTRP(bp), PACK(asize, 1)); PUT(HDRP(NEXT_BLKP(bp)), PACK(remain_size, 0)); PUT(FTRP(NEXT_BLKP(bp)), PACK(remain_size, 0)); }else{ PUT(HDRP(bp), PACK(GET_SIZE(HDRP(bp)), 1)); PUT(FTRP(bp), PACK(GET_SIZE(HDRP(bp)), 1)); } }
|
mm_realloc
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| void *mm_realloc(void *ptr, size_t size) { void *p; size_t copy_size; if (ptr == NULL) { p = mm_malloc(size); return p; } if (size == 0) { mm_free(ptr); return NULL; }
copy_size = GET_SIZE(ptr-WSIZE); p = mm_malloc(size); if (!p) { return NULL; }
if (size < copy_size) copy_size = size;
memcpy(p, ptr, copy_size); mm_free(ptr);
return p; }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| static void *find_fit(size_t asize) { void *bp = heap_listp; size_t size; while((size = GET_SIZE(HDRP(bp))) != 0){ if(size >= asize && !GET_ALLOC(HDRP(bp))) return bp; bp = NEXT_BLKP(bp); } return NULL; } static void place(void *bp, size_t asize) { size_t remain_size; remain_size = GET_SIZE(HDRP(bp)) - asize; if(remain_size >= DSIZE){ PUT(HDRP(bp), PACK(asize, 1)); PUT(FTRP(bp), PACK(asize, 1)); PUT(HDRP(NEXT_BLKP(bp)), PACK(remain_size, 0)); PUT(FTRP(NEXT_BLKP(bp)), PACK(remain_size, 0)); }else{ PUT(HDRP(bp), PACK(GET_SIZE(HDRP(bp)), 1)); PUT(FTRP(bp), PACK(GET_SIZE(HDRP(bp)), 1)); }
}
|
看完别人写的思路其实差不多懂了,懒得再写了。直接啃源码去了。