简单显示分配器的实现

Posted lan126

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了简单显示分配器的实现相关的知识,希望对你有一定的参考价值。

 

没有什么难以理解的地方

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有没有很好的工作我还没想到很好的方法检验.

以上是关于简单显示分配器的实现的主要内容,如果未能解决你的问题,请参考以下文章

如何在没有 dralogfragment 实例的情况下从适配器显示对话框片段?

如何在kotlin的片段内显示网格视图?

Android - 使用片段和简单的光标适配器填充列表视图

ListView 未显示在片段中

Android适配器之ArrayAdapterSimpleAdapter和BaseAdapter的简单用法

在android中显示隐藏片段