简单显示分配器的实现
没有什么难以理解的地方
static void *heap_listp; extern int mm_init(void); extern void *mm_malloc(size_t size); extern void mm_free(void *ptr); static void *extend_heap(size_t words); static void *coalesce(void *bp); static void *find_fit(size_t asize); static void *place(void *bp,size_t asize); /*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 amout (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 workd 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,comute 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))) 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); /*Extend the empty heap with a free block of CHUNKSIZE bytes*/ if(extend_heap(CHUNKSIZE/WSIZE) == NULL) return -1; return 0; } 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)); /*New block header and Free Epilogue*/ PUT(FTRP(bp),PACK(size,0)); /*New block footer*/ PUT(HDRP(NEXT_BLKP(bp)),PACK(0,1)); /*New Epilogue header*/ /*Coalesce if the previous block was free*/ return coalesce(bp); } 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) { /*Case 1*/ return bp; } else 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(HDRP(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)); } return bp; } 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); /*judge size*/ /*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 *find_fit(size_t asize) { char *bp = (heap_listp+DSIZE); /*get first block*/ size_t this_alloc=GET_ALLOC(HDRP(NEXT_BLKP(bp))); /*judge if 0*/ size_t this_size=GET_SIZE(HDRP(bp)); /*get size*/ while(!(this_alloc == 0x1 && this_size == 0)) { /*scan the list*/ if(this_alloc == 0x0 && this_size >= asize) return bp; /*get the good block*/ bp=NEXT_BLKP(bp); /*get the next one*/ this_alloc=GET_ALLOC(HDRP(NEXT_BLKP(bp))); this_size=GET_SIZE(HDRP(bp)); } return NULL; /*bad scan*/ } static void *place(void *bp,size_t asize){ size_t old_size=GET_SIZE(HDRP(bp)); /*save old size*/ if(asize == old_size) { /*same size*/ PUT(HDRP(bp),PACK(asize,1)); PUT(FTRP(bp),PACK(asize,1)); } else { /*samller size*/ size_t rem_size=old_size-asize; /*get the remain size*/ PUT(HDRP(bp),PACK(asize,1)); /*set the alloc*/ PUT(FTRP(bp),PACK(asize,1)); void *next_bp=NEXT_BLKP(bp); PUT(HDRP(next_bp),PACK(rem_size,0)); /*set alloc and size*/ PUT(FTRP(next_bp),PACK(rem_size,0)); } }
下面是memlib 注意MAX_HEAP 不要取太大不然开不了
#define MAX_HEAP (1<<20) /*Private global variables*/ static char *mem_heap; /*Points to first byte of heap*/ static char *mem_brk; /*Points to last byte of heap plus 1*/ static char *mem_max_addr; /*Max legal heap addr plus 1*/ /* *mem_init - Initialize the memory system model */ void mem_init(void) { mem_heap = (char*)malloc(MAX_HEAP); mem_brk = (char*)mem_heap; mem_max_addr = (char*)(mem_heap + MAX_HEAP); } /* *mem_sbrk - Simple model of the sbrk function. Extends the heap * by incr bytes and returns the start address of the new area.In * this model,the heap cannot be shrunk. */ void *mem_sbrk(int incr) { char *old_brk = mem_brk; if((incr < 0) || ((mem_brk + incr) > mem_max_addr)) { errno = ENOMEM; fprintf(stderr,"ERROR: memsbrk failed. Ran out of memory ...\n"); return (void*)-1; } mem_brk+=incr; return (void*)old_brk; }
加上相应的库函数就可以运行了.不过问题是mm_free有没有很好的工作我还没想到很好的方法检验.
Yosoro