这个LAB 是上完CMU CSAPP的16-20 LECTURE之后,就可以做了。
csapp 课程观看地址:https://search.bilibili.com/all?keyword=csapp&from_source=banner_search
lab 6 下载地址: http://csapp.cs.cmu.edu/3e/labs.html
找到MALLOC lab, 点击SELF-STUDY HANDOUT
第一个版本是使用了IMPLICT LIST, NEXT_FIT,快速达到83分。(30分钟)
随后实现老师上课说的单HEADER,不要FOOTER的策略,发现并没有很大提高。
随后开始对REALLOC优化,也只能提高到了89分。
从第三部分开始 完整实现了SEG FREE LIST + MEM CHECK(帮助我找到一个链表SIZE ORDER的BUG)从97分上升到了98分。
前置功课
1.看一遍WRITE UP
2.把书上相关章节的代码理解透
3.学习使用GDB
-
另外的DEBUG神技
任务目标
实现自己的 malloc
, free
, realloc
函数。
我们需要做的是完成在 mm.c
中的以下几个函数
int mm_init(void);
void *malloc(size_t size);
void free(void *ptr);
void *realloc(void *ptr, size_t size);
void mm_checkheap(int);
mm-init
:在这里执行所有的初始化操作,包括分配初始的堆区域。注意,必须在这里重新初始化所有的全局变量,并且不要调用mem.init
函数。成功的话返回 0 ,否则返回 -1malloc
:至少需要分配size
这么大的空间(可能因为对齐的原因会更大一点,8 byte 对齐),不能超出堆的范围,也不能覆盖其他已分配的区域free
:释放ptr
指针指向的区域(这个区域必须是已分配的),free(NULL)
什么都不做-
realloc
:重新分配,根据传入指针的不同,有不同的表现-
ptr
为 NULL 时,等同于malloc(size)
-
size
为 0 时,等同于free(ptr)
,需要返回 NULL -
ptr
不为 NULL 时,一定是指向一个已分配的空间的,就根据新的 size 的大小进行调整,并让ptr
指向新的地址(如果是新地址的话),并且旧的区域应该被释放。另外需要注意的是,需要把原来 block 的值复制过去
-
mm_checkheap
:扫描堆并检查其状态,注意,只有在检测到错误时才输出内容并调用exit
退出。mm_heapchecker(__Line__);
传入的参数是当前行数,方便大家找到错误位置。
memlib.c
模拟了内存系统,可以调用下面的方法来得到响应的信息:
-
void *mem_sbrk(int incr)
:让堆扩展incr
个字节,并返回新分配的地址的头指针 -
void *mem_heap_lo(void)
:返回指向堆的第一个字节的指针 -
void *mem_heap_hi(void)
:返回指向堆的最后一个字节的指针 -
size_t mem_heapsize(void)
:返回当前的堆大小 -
size_t mem_pagesize(void)
:返回系统的 page size
head checker 需要做的工作有:
- 检查堆(implicit list, explicit list, segregated list)
- Check epilogue and prologue blocks
- Check each block’s address alignment
- Check heap boundaries
- Check each block’s header and footer: size(minimum size, slignment), previous/net allocate/free bit consistency, header and footer matching each other
- Check coalescing: no two consecutive free blocks in the heap
- 检查 free list(explicit list, segregated list)
- All next/previous pointer are consistent (is A’s next pointer points ot B, B’s previous pointer should point to A)
- All free list pointers points between
mem_heap_lo()
andmem_heap_hi()
- Count free blocks by iterating through every block and traversing free list by pointers and see if they match
- All blocks in each list bucket fall within bucket size range(segregated list)
需要注意的地方:
- 不能改动
mm.h
,但是可以在mm.c
中添加static
方法使代码更好理解 -
mm.c
中不能定义任何全局 array, tree 或 list,但是可以定义全局 struct 和诸如 integer, float 和 pointer 等变量 - 返回的指针必须是 8-byte 对齐的
- 编译代码不能有警告
- 建议先实现 explcit free list
1.使用课本代码
首先把CSAPP 课本上的隐式链表法的代码抄下来,之后需要自己写2个函数
其中PLACE 这个函数要注意 如果差小于2 * DSIZE的 话,是没必要切割的。因为在这种做法中,最少的块代下也是2 * DSIZE。因为HEAD+FOOTER 花掉一个DISZE,还需要存数据然后按8对齐,所以至少还要一个DSIZE。
static void *find_fit(size_t asize)
{
char *bp = heap_listp;
size_t alloc;
size_t size;
while (GET_SIZE(HDRP(NEXT_BLKP(bp))) > 0) {
bp = NEXT_BLKP(bp);
alloc = GET_ALLOC(HDRP(bp));
if (alloc) continue;
size = GET_SIZE(HDRP(bp));
if (size < asize) continue;
return bp;
}
return NULL;
}
static void place(void *bp, size_t asize)
{
size_t size = GET_SIZE(HDRP(bp));
if ((size - asize) >= (2*DSIZE)) {
PUT(HDRP(bp),PACK(asize,1));
PUT(FTRP(bp),PACK(asize,1));
PUT(HDRP(NEXT_BLKP(bp)),PACK(size - asize,0));
PUT(FTRP(NEXT_BLKP(bp)),PACK(size - asize,0));
} else {
PUT(HDRP(bp),PACK(size,1));
PUT(FTRP(bp),PACK(size,1));
}
}
写完之后跑一下,发现最后2个应该是因为REALLOC 没有更新的原因而没过。
更新REALLOC
void *mm_realloc(void *ptr, size_t size)
{
if (ptr == NULL)
return mm_malloc(size);
if (size == 0) {
mm_free(ptr);
return NULL;
}
void *newptr;
size_t copySize;
newptr = mm_malloc(size);
if (newptr == NULL)
return NULL;
size = GET_SIZE(HDRP(ptr));
copySize = GET_SIZE(HDRP(newptr));
if (size < copySize)
copySize = size;
memcpy(newptr, ptr, copySize - WSIZE);
mm_free(ptr);
return newptr;
}
第一版最后得分
2. 尝试使用NEXT-FIT替代FIRST-FIT
跑分结果
代码改动如下
/*
* mm-naive.c - The fastest, least memory-efficient malloc package.
*
* In this naive approach, a block is allocated by simply incrementing
* the brk pointer. A block is pure payload. There are no headers or
* footers. Blocks are never coalesced or reused. Realloc is
* implemented directly using mm_malloc and mm_free.
*
* NOTE TO STUDENTS: Replace this header comment with your own header
* comment that gives a high level description of your solution.
*/
#include
#include
#include
#include
#include
#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 */
"[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)))
/* Basic constants and macros */
#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 a 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)))
static void *extend_heap(size_t words);
static void *find_fit(size_t asize);
static void place(void *bp, size_t asize);
static void *coalesce(void *bp);
static char *heap_listp;
static char *pre_listp;
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 */
/* Coalesce if the previous block was free */
return coalesce(bp);
}
/*
* mm_init - initialize the malloc package.
*/
int mm_init(void)
{
/* Create the initial empty heap */
if ((heap_listp = mem_sbrk(4*WSIZE)) == (void *)-1)
return -1;
PUT(heap_listp, 0); /* Alignment padding */
PUT(heap_listp + (1*WSIZE), PACK(DSIZE, 1)); /* Prologue header */
PUT(heap_listp + (2*WSIZE), PACK(DSIZE, 1)); /* Prologue footer */
PUT(heap_listp + (3*WSIZE), PACK(0, 1)); /* Epilogue header */
heap_listp += (2*WSIZE);
pre_listp = heap_listp;
/* Extend the empty heap with a free block of CHUNKSIZE bytes */
if (extend_heap(CHUNKSIZE/WSIZE) == NULL)
return -1;
return 0;
}
static void *find_fit(size_t asize)
{
char *bp = pre_listp;
size_t alloc;
size_t size;
while (GET_SIZE(HDRP(NEXT_BLKP(bp))) > 0) {
bp = NEXT_BLKP(bp);
alloc = GET_ALLOC(HDRP(bp));
if (alloc) continue;
size = GET_SIZE(HDRP(bp));
if (size < asize) continue;
return bp;
}
bp = heap_listp;
while (bp != pre_listp) {
bp = NEXT_BLKP(bp);
alloc = GET_ALLOC(HDRP(bp));
if (alloc) continue;
size = GET_SIZE(HDRP(bp));
if (size < asize) continue;
return bp;
}
return NULL;
}
static void place(void *bp, size_t asize)
{
size_t size = GET_SIZE(HDRP(bp));
if ((size - asize) >= (2*DSIZE)) {
PUT(HDRP(bp),PACK(asize,1));
PUT(FTRP(bp),PACK(asize,1));
PUT(HDRP(NEXT_BLKP(bp)),PACK(size - asize,0));
PUT(FTRP(NEXT_BLKP(bp)),PACK(size - asize,0));
} else {
PUT(HDRP(bp),PACK(size,1));
PUT(FTRP(bp),PACK(size,1));
}
pre_listp = 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)
{
size_t asize; /* Adjusted block size */
size_t extendsize; /* Amount to extend heap if no fit */
char *bp;
/* Ignore spurious requests */
if (size == 0)
return NULL;
/* Adjust block size to include overhead and alignment reqs. */
if (size <= DSIZE)
asize = 2*DSIZE;
else
asize = DSIZE * ((size + (DSIZE) + (DSIZE-1)) / DSIZE);
/* Search the free list for a fit */
if ((bp = find_fit(asize)) != NULL) {
place(bp, asize);
return bp;
}
/* No fit found. Get more memory and place the block */
extendsize = MAX(asize,CHUNKSIZE);
if ((bp = extend_heap(extendsize/WSIZE)) == NULL)
return NULL;
place(bp, asize);
return 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));
//int isPre = (pre_listp == bp);
if (prev_alloc && next_alloc) { // Case 1
pre_listp = bp;
return bp;
}
if (prev_alloc && !next_alloc) { /* Case 2 */
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) { /* Case 3 */
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 { /* Case 4 */
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);
}
pre_listp = bp;
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)
{
if (ptr == NULL)
return mm_malloc(size);
if (size == 0)
mm_free(ptr);
void *newptr;
size_t copySize;
newptr = mm_malloc(size);
if (newptr == NULL)
return NULL;
size = GET_SIZE(HDRP(ptr));
copySize = GET_SIZE(HDRP(newptr));
if (size < copySize)
copySize = size;
memcpy(newptr, ptr, copySize - WSIZE);
mm_free(ptr);
return newptr;
}
3. 尝试使用PPT的方法去掉ALLOC BLOCK的FOOTER
跑分差不多
/*
* mm-naive.c - The fastest, least memory-efficient malloc package.
*
* In this naive approach, a block is allocated by simply incrementing
* the brk pointer. A block is pure payload. There are no headers or
* footers. Blocks are never coalesced or reused. Realloc is
* implemented directly using mm_malloc and mm_free.
*
* NOTE TO STUDENTS: Replace this header comment with your own header
* comment that gives a high level description of your solution.
*/
#include
#include
#include
#include
#include
#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 */
"[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)))
/* Basic constants and macros */
#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))
#define PREALLOC(x) ((!x) ? 0 : 2)
/* Pack a size and allocated bit into a word */
#define PACK(size, prealloc, alloc) ((size) | (PREALLOC(prealloc)) | (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)
#define GET_PREALLOC(p) (GET(p) & 0x2)
/* 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)))
static void *extend_heap(size_t words);
static void *find_fit(size_t asize);
static void place(void *bp, size_t asize);
static void *coalesce(void *bp);
inline void set_next_prealloc(void* bp, size_t prealloc);
static char *heap_listp;
static char *pre_listp;
static void *extend_heap(size_t words)
{
char *bp;
size_t size, prealloc;
/* 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 */
prealloc = GET_PREALLOC(HDRP(bp));
PUT(HDRP(bp), PACK(size,prealloc, 0)); /* Free block header */
PUT(FTRP(bp), PACK(size,prealloc, 0)); /* Free block footer */
PUT(HDRP(NEXT_BLKP(bp)), PACK(0,0, 1)); /* New epilogue header */
/* Coalesce if the previous block was free */
return coalesce(bp);
}
/*
* mm_init - initialize the malloc package.
*/
int mm_init(void)
{
/* Create the initial empty heap */
if ((heap_listp = mem_sbrk(4*WSIZE)) == (void *)-1)
return -1;
PUT(heap_listp, 0); /* Alignment padding */
PUT(heap_listp + (1*WSIZE), PACK(DSIZE,1, 1)); /* Prologue header */
PUT(heap_listp + (2*WSIZE), PACK(DSIZE,1, 1)); /* Prologue footer */
PUT(heap_listp + (3*WSIZE), PACK(0,1, 1)); /* Epilogue header */
heap_listp += DSIZE;
pre_listp = heap_listp;
/* Extend the empty heap with a free block of CHUNKSIZE bytes */
if (extend_heap(CHUNKSIZE/WSIZE) == NULL)
return -1;
return 0;
}
static void *find_fit(size_t asize)
{
char *bp = pre_listp;
size_t alloc;
size_t size;
while (GET_SIZE(HDRP(NEXT_BLKP(bp))) > 0) {
bp = NEXT_BLKP(bp);
alloc = GET_ALLOC(HDRP(bp));
if (alloc) continue;
size = GET_SIZE(HDRP(bp));
if (size < asize) continue;
return bp;
}
bp = heap_listp;
while (bp != pre_listp) {
bp = NEXT_BLKP(bp);
alloc = GET_ALLOC(HDRP(bp));
if (alloc) continue;
size = GET_SIZE(HDRP(bp));
if (size < asize) continue;
return bp;
}
return NULL;
}
static void place(void *bp, size_t asize)
{
size_t size = GET_SIZE(HDRP(bp));
if ((size - asize) >= DSIZE) {
PUT(HDRP(bp),PACK(asize,1,1));
//PUT(FTRP(bp),PACK(asize,1,1));
PUT(HDRP(NEXT_BLKP(bp)),PACK(size - asize,1,0));
PUT(FTRP(NEXT_BLKP(bp)),PACK(size - asize,1,0));
set_next_prealloc(bp,0);
} else {
PUT(HDRP(bp),PACK(size,1,1));
set_next_prealloc(bp,1);
//PUT(FTRP(bp),PACK(size,1,1));
}
pre_listp = 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)
{
size_t asize; /* Adjusted block size */
size_t extendsize; /* Amount to extend heap if no fit */
char *bp;
/* Ignore spurious requests */
if (size == 0)
return NULL;
/* Adjust block size to include overhead and alignment reqs. */
if (size <= WSIZE)
asize = DSIZE;
else
asize = DSIZE * ((size + (WSIZE) + (DSIZE-1)) / DSIZE);
/* Search the free list for a fit */
if ((bp = find_fit(asize)) != NULL) {
place(bp, asize);
return bp;
}
/* No fit found. Get more memory and place the block */
extendsize = MAX(asize,CHUNKSIZE);
if ((bp = extend_heap(extendsize/WSIZE)) == NULL)
return NULL;
place(bp, asize);
return bp;
}
static void *coalesce(void *bp)
{
size_t prev_alloc = GET_PREALLOC(HDRP(bp));
size_t next_alloc = GET_ALLOC(HDRP(NEXT_BLKP(bp)));
size_t size = GET_SIZE(HDRP(bp));
if (prev_alloc && !next_alloc) { /* Case 2 */
size += GET_SIZE(HDRP(NEXT_BLKP(bp)));
PUT(HDRP(bp), PACK(size,1, 0));
PUT(FTRP(bp), PACK(size,1, 0));
}
else if (!prev_alloc && next_alloc) { /* Case 3 */
size += GET_SIZE(HDRP(PREV_BLKP(bp)));
PUT(FTRP(bp), PACK(size,1, 0));
PUT(HDRP(PREV_BLKP(bp)), PACK(size,1, 0));
bp = PREV_BLKP(bp);
}
else if (!prev_alloc && !next_alloc){ /* Case 4 */
size += GET_SIZE(HDRP(PREV_BLKP(bp))) +
GET_SIZE(FTRP(NEXT_BLKP(bp)));
PUT(HDRP(PREV_BLKP(bp)), PACK(size,1, 0));
PUT(FTRP(NEXT_BLKP(bp)), PACK(size,1, 0));
bp = PREV_BLKP(bp);
}
set_next_prealloc(bp,0);
pre_listp = bp;
return bp;
}
/*
* mm_free - Freeing a block does nothing.
*/
void mm_free(void *bp)
{
size_t size = GET_SIZE(HDRP(bp));
size_t prealloc = GET_PREALLOC(HDRP(bp));
PUT(HDRP(bp), PACK(size,prealloc, 0));
PUT(FTRP(bp), PACK(size,prealloc, 0));
coalesce(bp);
}
/*
* mm_realloc - Implemented simply in terms of mm_malloc and mm_free
*/
void *mm_realloc(void *ptr, size_t size)
{
if (ptr == NULL)
return mm_malloc(size);
if (size == 0)
mm_free(ptr);
void *newptr;
size_t copySize;
newptr = mm_malloc(size);
if (newptr == NULL)
return NULL;
size = GET_SIZE(HDRP(ptr));
copySize = GET_SIZE(HDRP(newptr));
if (size < copySize)
copySize = size;
memcpy(newptr, ptr, copySize - WSIZE);
mm_free(ptr);
return newptr;
}
inline void set_next_prealloc(void* bp, size_t prealloc)
{
size_t size = GET_SIZE(HDRP(NEXT_BLKP(bp)));
size_t alloc = GET_ALLOC(HDRP(NEXT_BLKP(bp)));
PUT(HDRP(NEXT_BLKP(bp)), PACK(size,prealloc,alloc));
}
经过对REALLOC方法做了优化,针对最后2个CASE,代码最终获得了89分。
看来课本赠送的方法很难上90分了。 下面就要自己实现一把老师上课讲的Segregated Free Lists
4. 实现Segregated Free Lists
在写代码前必须心中要有代码的架子,然后依据骨架来填写代码。
1.首先需要维护一个数组来存Segregated Free Lists
大小依次为{1}{2~3}{4~7}{8~15}...{2048~4095}... 也就是根据2的幂来。然后保证链表的大小有序性。例如第一条链,A是B的successor,B是A的predecessor,A的大小小于等于B
2.明确ALLOC块结构 和 FREE块结构。根据显示链表法可得。
那么如果是FREE BLOCK,就会有如下的宏方法。
#define PRED_PTR(ptr) ((void *)(ptr))
#define SUCC_PTR(ptr) ((void *)(ptr) + WSIZE)
#define PRED(ptr) (*(void **)(ptr))
#define SUCC(ptr) (*(void **)(SUCC_PTR(ptr)))
因为多了PTR属性,我们还需要去SET PTR
#define SET_PTR(p, ptr) (*(unsigned int *)(p) = (unsigned int)(ptr))
3. 明确基本算法
3.1 INIT HEAP的时候要初始化seg_free_lists,随后是课本代码
在EXTEND HEAP的时候,拿到FREE块,根据SIZE放进对应的空闲链表。
3.2 MALLOC 的时候,计算ASIZE。随后用右移,来定位到对应的seg_free_list,随后进行循环,找到第一个满足的FREE BLOCK。做PLACE操作。如果没有找到就到下一个seg_free_list去找。全没找到,那么退出循环时;指针应该为NULL,就要EXTEND HEAP。
3.3 FREE, 把对应的块先置为FREE状态。进行coalesce。直接分4种情况考虑。(下面4种CASE 的意义,和课本上一致,不做额外解释)
CASE 1, 需要进行INSERT NODE, return ptr
CASE 2, 合并之后,DELETE后面的NODE,最后INSERT
CASE 3, 删除前面的节点,合并,指针移到之前,INSERT
CASE 4, 删除前后的节点,合并,指针移到之前,INSERT
3.4 REALLOC 算出ASIZE,如果ASIZE 小于原来的块大小,直接返回原来的块。(这种做法在我做小实验的时候,发现UTIL率更高,就是有小的也不切割)
否则检查是否可以将后一个块 或 前一个块吸纳进来。(当然根据WRITES UP 这个优化的REALLOC,可以最后写)
都不行就只能MALLOC ,MEMCPY, 然后FREE。
4. 如何写辅助函数
4.1 INSERT NODE(void *ptr, size_t size)
对SIZE 右移,找到最先能符合要求的链。然后找到大小合适的位置进行插入。
分4个情况,空链插入,开头插入,结尾插入,中间插入。
而链表连接就通过我们之前的宏。举个例子
SET_PTR(PRED_PTR(ptr), pre_ptr);
SET_PTR(SUCC_PTR(pre_ptr), ptr);
4.2 DELETE NODE(void *ptr)
根据PTR取到SIZE,对SIZE 右移,找到最先能符合要求的链。
还是和上面一样分为4种可能性。比如在中间的可以这么写
SET_PTR(SUCC_PTR(PRED(ptr)), SUCC(ptr));
SET_PTR(PRED_PTR(SUCC(ptr)), PRED(ptr));
4.3 PLACE(void *ptr, size_t size)
计算剩余块的大小,小于 2 * DSIZE
直接更新HEADER, FOOTER。
如果SIZE大于一个MAGIC NUMBER 需要放在后面,把前半部分切割出来。
<的话,放在前面。这就需要重新返回BP指针
为什么这样呢?
否则分离原块,但这里要注意这样一种情况(在binary-bal.rep和binary2-bal.rep有体现):
* 如果每次allocate的块大小按照小、大、小、大的连续顺序来的话,我们的free块将会被“拆”成以下这种结构:
* 其中s代表小的块,B代表大的块
s B s B s B s B
+--+----------+--+----------+-+-----------+-+---------+
| | | | | | | | |
| | | | | | | | |
| | | | | | | | |
+--+----------+--+----------+-+-----------+-+---------+
* 这样看起来没什么问题,但是如果程序后来free的时候不是按照”小、大、小、大“的顺序来释放的话就会出现“external fragmentation”
* 例如当程序将大的块全部释放了,但小的块依旧是allocated:
s s s s
+--+----------+--+----------+-+-----------+-+---------+
| | | | | | | | |
| | Free | | Free | | Free | | Free |
| | | | | | | | |
+--+----------+--+----------+-+-----------+-+---------+
* 这样即使我们有很多free的大块可以使用,但是由于他们不是连续的,我们不能将它们合并,如果下一次来了一个大小为B+1的allocate请求
* 我们就还需要重新去找一块Free块
* 与此相反,如果我们根据allocate块的大小将小的块放在连续的地方,将达到开放在连续的地方:
s s s s s s B B B
+--+--+--+--+--+--+----------+------------+-----------+
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
+--+--+--+--+--+--+----------+------------+-----------+
* 这样即使程序连续释放s或者B,我们也能够合并free块,不会产生external fragmentation
* 这里“大小”相对判断是根据binary-bal.rep和binary2-bal.rep这两个文件设置的,我这里在96附近能够达到最优值
*
4. 定了数据结构和算法后,实现void mm_checkheap(int verbose)
参考代码
http://csapp.cs.cmu.edu/3e/ics3/code/vm/malloc/mm.c
先把架子搭好
/* below code if for check heap invarints */
/*
* mm_checkheap - Check the heap for correctness
*/
void mm_checkheap(int verbose)
{
checkheap(verbose);
}
//heap level
void checkheap(int verbose)
{
char *bp = heap_listp;
if (verbose)
printf("Heap (%p):\n", heap_listp);
if ((GET_SIZE(HDRP(heap_listp)) != DSIZE) || !GET_ALLOC(HDRP(heap_listp)))
printf("Bad prologue header\n");
// block level
checkblock(heap_listp);
int pre_free = 0;
for (bp = heap_listp; GET_SIZE(HDRP(bp)) > 0; bp = NEXT_BLKP(bp)) {
if (verbose)
printblock(bp);
int cur_free = checkblock(bp);
if (pre_free && cur_free) {
printf("Contiguous free blocks\n");
}
}
//list level
int i = 0;
for (; i < LIST_MAX; i++) {
if (verbose)
printlist(bp);
checklist(seg_free_lists[i]);
}
if (verbose)
printblock(bp);
if ((GET_SIZE(HDRP(bp)) != 0) || !(GET_ALLOC(HDRP(bp))))
printf("Bad epilogue header\n");
}
4.1 实现check block, print block
static void printblock(void *bp)
{
long int hsize, halloc, fsize, falloc;
hsize = GET_SIZE(HDRP(bp));
halloc = GET_ALLOC(HDRP(bp));
fsize = GET_SIZE(FTRP(bp));
falloc = GET_ALLOC(FTRP(bp));
if (hsize == 0) {
printf("%p: EOL\n", bp);
return;
}
printf("%p: header: [%ld:%c] footer: [%ld:%c]\n", bp,
hsize, (halloc ? 'a' : 'f'),
fsize, (falloc ? 'a' : 'f'));
}
static int checkblock(void *bp)
{
//area is aligned
if ((size_t)bp % 8)
printf("Error: %p is not doubleword aligned\n", bp);
//header and footer match
if (GET(HDRP(bp)) != GET(FTRP(bp)))
printf("Error: header does not match footer\n");
size_t size = GET_SIZE(HDRP(bp));
//size is valid
if (size % 8)
printf("Error: %p payload size is not doubleword aligned\n", bp);
return GET_ALLOC(HDRP(bp));
}
4.2 实现check list, print list
static void printlist(void *i, long size)
{
long int hsize, halloc;
for(;i != NULL;i = SUCC(i))
{
hsize = GET_SIZE(HDRP(i));
halloc = GET_ALLOC(HDRP(i));
printf("[listnode %ld] %p: header: [%ld:%c] prev: [%p] next: [%p]\n",
size, i,
hsize, (halloc ? 'a' : 'f'),
PRED(i), SUCC(i));
}
}
static void checklist(void *i, size_t tar)
{
void *pre = NULL;
long int hsize, halloc;
for(;i != NULL;i = SUCC(i))
{
if (PRED(i) != pre) printf("Error: pred point error\n");
if (pre != NULL && SUCC(pre) != i) printf("Error: succ point error\n");
hsize = GET_SIZE(HDRP(i));
halloc = GET_ALLOC(HDRP(i));
if (halloc) printf("Error: list node should be free\n");
if (pre != NULL && (GET_SIZE(HDRP(pre)) > hsize))
printf("Error: list size order error\n");
if (hsize < tar || ((tar != (1<<15)) && (hsize > (tar << 1)-1)))
printf("Error: list node size error\n");
pre = i;
}
}
5.最终代码实现
使用DEBUG 模式 , CHECK HEAP, 发现链表大小的顺序有错。虽然也能过。
修复了这个BUG后
/*
* mm-naive.c - The fastest, least memory-efficient malloc package.
*
* In this naive approach, a block is allocated by simply incrementing
* the brk pointer. A block is pure payload. There are no headers or
* footers. Blocks are never coalesced or reused. Realloc is
* implemented directly using mm_malloc and mm_free.
*
* NOTE TO STUDENTS: Replace this header comment with your own header
* comment that gives a high level description of your solution.
*/
#include
#include
#include
#include
#include
#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 */
"[email protected]",
/* Second member's full name (leave blank if none) */
"",
/* Second member's email address (leave blank if none) */
""
};
#define DEBUG 1
/* If you want debugging output, use the following macro. When you hand
* in, remove the #define DEBUG line. */
#ifdef DEBUG
# define DBG_PRINTF(...) printf(__VA_ARGS__)
# define CHECKHEAP(verbose) mm_checkheap(verbose)
#else
# define DBG_PRINTF(...)
# define CHECKHEAP(verbose)
#endif
/* 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 LISTMAX 16
/* Basic constants and macros */
#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 INITCHUNKSIZE (1<<6)
#define MAX(x, y) ((x) > (y)? (x) : (y))
#define MIN(x, y) ((x) < (y)? (x) : (y))
/* Pack a size and allocated bit into a 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)))
/* for explict linkedlist */
#define PRED_PTR(ptr) ((char *)(ptr))
#define SUCC_PTR(ptr) ((char *)(ptr) + WSIZE)
#define PRED(ptr) (*(char **)(ptr))
#define SUCC(ptr) (*(char **)(SUCC_PTR(ptr)))
#define SET_PTR(p, ptr) (*(unsigned int *)(p) = (unsigned int)(ptr))
static void *extend_heap(size_t words);
static void *place(void *bp, size_t asize);
static void *coalesce(void *bp);
static void insert_node(void *bp, size_t size);
static void delete_node(void *bp);
static size_t get_asize(size_t size);
static void *realloc_coalesce(void *bp,size_t newSize,int *isNextFree);
static void realloc_place(void *bp,size_t asize);
void checkheap(int verbose);
void mm_checkheap(int verbose);
void *seg_free_lists[LISTMAX];
char *heap_listp;
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 */
/* Coalesce if the previous block was free include insert*/
return coalesce(bp);
}
/*
* mm_init - initialize the malloc package.
*/
int mm_init(void)//done
{
int i;
/* initiliaze seg_free_lists */
for (i = 0; i < LISTMAX; i++) {
seg_free_lists[i] = NULL;
}
/* Create the initial empty heap */
if ((heap_listp = mem_sbrk(4*WSIZE)) == (void *)-1)
return -1;
PUT(heap_listp, 0); /* Alignment padding */
PUT(heap_listp + (1*WSIZE), PACK(DSIZE, 1)); /* Prologue header */
PUT(heap_listp + (2*WSIZE), PACK(DSIZE, 1)); /* Prologue footer */
PUT(heap_listp + (3*WSIZE), PACK(0, 1)); /* Epilogue header */
heap_listp += (2*WSIZE);
/* Extend the empty heap with a free block of CHUNKSIZE bytes */
if (extend_heap(INITCHUNKSIZE/WSIZE) == NULL)
return -1;
CHECKHEAP(1);
return 0;
}
static void *place(void *bp, size_t asize)//done
{
size_t size = GET_SIZE(HDRP(bp));
delete_node(bp);
if ((size - asize) < (2*DSIZE)) {
PUT(HDRP(bp),PACK(size,1));
PUT(FTRP(bp),PACK(size,1));
} else if (asize >= 96) {
PUT(HDRP(bp),PACK(size - asize,0));
PUT(FTRP(bp),PACK(size - asize,0));
PUT(HDRP(NEXT_BLKP(bp)),PACK(asize,1));
PUT(FTRP(NEXT_BLKP(bp)),PACK(asize,1));
insert_node(bp,size - asize);
return NEXT_BLKP(bp);
} else {
PUT(HDRP(bp),PACK(asize,1));
PUT(FTRP(bp),PACK(asize,1));
PUT(HDRP(NEXT_BLKP(bp)),PACK(size - asize,0));
PUT(FTRP(NEXT_BLKP(bp)),PACK(size - asize,0));
insert_node(NEXT_BLKP(bp),size - asize);
}
return bp;
}
static void insert_node(void *bp, size_t size)
{
int tar = 0;
size_t j;
for (j = size; (j > 1) && (tar < LISTMAX - 1); ) {
j >>= 1;
tar++;
}
char *i = seg_free_lists[tar];
char *pre = NULL;
while ((i != NULL) && (size > GET_SIZE(HDRP(i)))) {
pre = i;
i = SUCC(i);
}// i should be first node size >= input size
if (i == NULL && pre == NULL) {//empty list
seg_free_lists[tar] = bp;
SET_PTR(PRED_PTR(bp), NULL);
SET_PTR(SUCC_PTR(bp), NULL);
} else if (i == NULL && pre != NULL) {// add the last
SET_PTR(PRED_PTR(bp), pre);
SET_PTR(SUCC_PTR(bp), NULL);
SET_PTR(SUCC_PTR(pre), bp);
} else if (pre == NULL) {// add the first
seg_free_lists[tar] = bp;
SET_PTR(PRED_PTR(i), bp);
SET_PTR(SUCC_PTR(bp), i);
SET_PTR(PRED_PTR(bp), NULL);
} else {
SET_PTR(PRED_PTR(bp), pre);
SET_PTR(SUCC_PTR(bp), i);
SET_PTR(PRED_PTR(i), bp);
SET_PTR(SUCC_PTR(pre), bp);
}
}
static void delete_node(void *bp)//done
{
size_t size = GET_SIZE(HDRP(bp)), j;
int tar = 0;
for (j = size; (j > 1) && (tar < LISTMAX - 1); j >>= 1) {
tar++;
}
if (PRED(bp) == NULL) { // first one
seg_free_lists[tar] = SUCC(bp);
if (SUCC(bp) != NULL)
SET_PTR(PRED_PTR(SUCC(bp)), NULL);
} else if (SUCC(bp) == NULL) { //last one
SET_PTR(SUCC_PTR(PRED(bp)), NULL);
} else {
SET_PTR(SUCC_PTR(PRED(bp)), SUCC(bp));
SET_PTR(PRED_PTR(SUCC(bp)), PRED(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)
{
size_t asize, search; /* Adjusted block size */
size_t extendsize; /* Amount to extend heap if no fit */
char *bp = NULL;
/* Ignore spurious requests */
if (size == 0)
return NULL;
/* Adjust block size to include overhead and alignment reqs. */
asize = get_asize(size);
search = asize;
int target;
for (target = 0; target < LISTMAX; target++, search >>= 1) {
/* find target seg_free_list*/
if ((search > 1) || (seg_free_lists[target] == NULL)) continue;
char *i = seg_free_lists[target];
for(;i != NULL;i = SUCC(i))
{
if (GET_SIZE(HDRP(i)) < asize) continue;
bp = i;
break;
}
if (bp != NULL) break;
}
if (bp == NULL) {
/* No fit found. Get more memory and place the block */
extendsize = MAX(asize,CHUNKSIZE);
if ((bp = extend_heap(extendsize/WSIZE)) == NULL)
return NULL;
}
bp = place(bp, asize);
CHECKHEAP(1);
return bp;
}
static void *coalesce(void *bp)
{
size_t prev_alloc = GET_ALLOC(HDRP(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) { /* Case 2 */
size += GET_SIZE(HDRP(NEXT_BLKP(bp)));
delete_node(NEXT_BLKP(bp));
PUT(HDRP(bp), PACK(size, 0));
PUT(FTRP(bp), PACK(size,0));
}
else if (!prev_alloc && next_alloc) { /* Case 3 */
size += GET_SIZE(HDRP(PREV_BLKP(bp)));
delete_node(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){ /* Case 4 */
size += GET_SIZE(HDRP(PREV_BLKP(bp))) +
GET_SIZE(FTRP(NEXT_BLKP(bp)));
delete_node(PREV_BLKP(bp));
delete_node(NEXT_BLKP(bp));
PUT(HDRP(PREV_BLKP(bp)), PACK(size, 0));
PUT(FTRP(NEXT_BLKP(bp)), PACK(size, 0));
bp = PREV_BLKP(bp);
}
insert_node(bp,size);
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);
CHECKHEAP(1);
}
/*
* mm_realloc - Implemented simply in terms of mm_malloc and mm_free
*/
void *mm_realloc(void *ptr, size_t size)
{
if (ptr == NULL)
return mm_malloc(size);
if (size == 0) {
mm_free(ptr);
return NULL;
}
void *newptr;
size_t asize, oldsize;
oldsize = GET_SIZE(HDRP(ptr));
asize = get_asize(size);
if(oldsizeasize)
{/*just change the size of ptr*/
realloc_place(ptr,asize);
CHECKHEAP(1);
return ptr;
}
CHECKHEAP(1);
return ptr;
}
static size_t get_asize(size_t size)
{
size_t asize;
if(size <= DSIZE){
asize = 2*(DSIZE);
}else{
asize = ALIGN(size + DSIZE);
}
return asize;
}
static void *realloc_coalesce(void *bp,size_t newSize,int *isNextFree)
{
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));
*isNextFree = 0;
/*coalesce the block and change the point*/
if(prev_alloc && !next_alloc)
{
size += GET_SIZE(HDRP(NEXT_BLKP(bp)));
if(size>=newSize)
{
delete_node(NEXT_BLKP(bp));
PUT(HDRP(bp), PACK(size,1));
PUT(FTRP(bp), PACK(size,1));
*isNextFree = 1;
}
}
else if(!prev_alloc && next_alloc)
{
size += GET_SIZE(HDRP(PREV_BLKP(bp)));
if(size>=newSize)
{
delete_node(PREV_BLKP(bp));
PUT(FTRP(bp),PACK(size,1));
PUT(HDRP(PREV_BLKP(bp)),PACK(size,1));
bp = PREV_BLKP(bp);
}
}
else if(!prev_alloc && !next_alloc)
{
size +=GET_SIZE(FTRP(NEXT_BLKP(bp)))+ GET_SIZE(HDRP(PREV_BLKP(bp)));
if(size>=newSize)
{
delete_node(PREV_BLKP(bp));
delete_node(NEXT_BLKP(bp));
PUT(FTRP(NEXT_BLKP(bp)),PACK(size,1));
PUT(HDRP(PREV_BLKP(bp)),PACK(size,1));
bp = PREV_BLKP(bp);
}
}
return bp;
}
static void realloc_place(void *bp,size_t asize)
{
size_t csize = GET_SIZE(HDRP(bp));
/*
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));
coalesce(bp);
}
else
{
PUT(HDRP(bp),PACK(csize,1));
PUT(FTRP(bp),PACK(csize,1));
} */
PUT(HDRP(bp),PACK(csize,1));
PUT(FTRP(bp),PACK(csize,1));
}
/* below code if for check heap invarints */
static void printblock(void *bp)
{
long int hsize, halloc, fsize, falloc;
hsize = GET_SIZE(HDRP(bp));
halloc = GET_ALLOC(HDRP(bp));
fsize = GET_SIZE(FTRP(bp));
falloc = GET_ALLOC(FTRP(bp));
if (hsize == 0) {
printf("%p: EOL\n", bp);
return;
}
printf("%p: header: [%ld:%c] footer: [%ld:%c]\n", bp,
hsize, (halloc ? 'a' : 'f'),
fsize, (falloc ? 'a' : 'f'));
}
static int checkblock(void *bp)
{
//area is aligned
if ((size_t)bp % 8)
printf("Error: %p is not doubleword aligned\n", bp);
//header and footer match
if (GET(HDRP(bp)) != GET(FTRP(bp)))
printf("Error: header does not match footer\n");
size_t size = GET_SIZE(HDRP(bp));
//size is valid
if (size % 8)
printf("Error: %p payload size is not doubleword aligned\n", bp);
return GET_ALLOC(HDRP(bp));
}
static void printlist(void *i, long size)
{
long int hsize, halloc;
for(;i != NULL;i = SUCC(i))
{
hsize = GET_SIZE(HDRP(i));
halloc = GET_ALLOC(HDRP(i));
printf("[listnode %ld] %p: header: [%ld:%c] prev: [%p] next: [%p]\n",
size, i,
hsize, (halloc ? 'a' : 'f'),
PRED(i), SUCC(i));
}
}
static void checklist(void *i, size_t tar)
{
void *pre = NULL;
long int hsize, halloc;
for(;i != NULL;i = SUCC(i))
{
if (PRED(i) != pre) printf("Error: pred point error\n");
if (pre != NULL && SUCC(pre) != i) printf("Error: succ point error\n");
hsize = GET_SIZE(HDRP(i));
halloc = GET_ALLOC(HDRP(i));
if (halloc) printf("Error: list node should be free\n");
if (pre != NULL && (GET_SIZE(HDRP(pre)) > hsize))
printf("Error: list size order error\n");
if (hsize < tar || ((tar != (1<<15)) && (hsize > (tar << 1)-1)))
printf("Error: list node size error\n");
pre = i;
}
}
/*
* mm_checkheap - Check the heap for correctness
*/
void mm_checkheap(int verbose)
{
checkheap(verbose);
}
//heap level
void checkheap(int verbose)
{
char *bp = heap_listp;
if (verbose)
printf("Heap (%p):\n", heap_listp);
if ((GET_SIZE(HDRP(heap_listp)) != DSIZE) || !GET_ALLOC(HDRP(heap_listp)))
printf("Bad prologue header\n");
// block level
checkblock(heap_listp);
int pre_free = 0;
for (bp = heap_listp; GET_SIZE(HDRP(bp)) > 0; bp = NEXT_BLKP(bp)) {
if (verbose)
printblock(bp);
int cur_free = checkblock(bp);
//no contiguous free blocks
if (pre_free && cur_free) {
printf("Contiguous free blocks\n");
}
}
//list level
int i = 0, tarsize = 1;
for (; i < LISTMAX; i++) {
if (verbose)
printlist(seg_free_lists[i], tarsize);
checklist(seg_free_lists[i],tarsize);
tarsize <<= 1;
}
if (verbose)
printblock(bp);
if ((GET_SIZE(HDRP(bp)) != 0) || !(GET_ALLOC(HDRP(bp))))
printf("Bad epilogue header\n");
}