<@乌龟:>手动实现C语言运行库(1) 堆内存分配,malloc and free

    最近看到了<程序员的自我修养>这本书, 对书中大部分的底层知识兴趣不算太大,不过对最后的一章,C语言运行库的实现非常的感兴趣,于是就依葫芦画瓢的实现了一下,今天花了一点时间完成了堆内存分配的内容.

    就不多说太多了,直接贴贴代码,方便自己和别人日后查询,另外代码中有几处的错误,这里也标明了.

   1: //定义的一个Helper结构体,描述一片空间
   2: typedef struct _heap_helper
   3: {
   4:     //是否这个空间被使用
   5:     enum 
   6:     {
   7:         HEAP_BLOCK_FREE = 0xABABABAB,
   8:         HEAP_BLOCK_USED = 0xCDCDCDCD,
   9:     } type;
  10:  
  11:     //这片空间的大小(含头部)
  12:     unsigned size;
  13:     struct _heap_helper* next;
  14:     struct _heap_helper* prev;
  15: } heap_header;
  16:  
  17: #define ADDR_ADD(a,o) (((char*)(a)) + o)
  18: #define HEADER_SIZE (sizeof(heap_helper))
  19:  
  20: static heap_header* list_head = NULL;
  21:  
  22: void* malloc(unsigned size)
  23: {
  24:     heap_header *header;
  25:  
  26:     if (size == 0)
  27:     {
  28:         return NULL;
  29:     }
  30:  
  31:     header = list_head;
  32:     while (header != NULL)
  33:     {
  34:         //如果这片空间已经被使用,则跳至下片空间
  35:         if (header->type == HEAP_BLOCK_USED)
  36:         {
  37:             header = header->next;
  38:             continue;
  39:         }
  40:  
  41:         //如果刚好能够容纳size的内存,则标记
  42:         if (header->size > size + HEADER_SIZE && 
  43:             header->size <= size + HEADER_SIZE * 2)
  44:         {
  45:             header->type = HEAP_BLOCK_USED;
  46:             //原书的错误, 没有这个return
  47:             return ADDR_ADD(header,HEADER_SIZE);
  48:         }
  49:  
  50:         //如果这片空间足够大,则分割
  51:         if (header->size > size + HEADER_SIZE * 2)
  52:         {
  53:             heap_header* next = (heap_header*)ADDR_ADD(header,size + HEADER_SIZE);
  54:             next->prev = header;
  55:             next->next = header->next;
  56:             next->type = HEAP_BLOCK_FREE;
  57:             next->size = header->size - (size - HEADER_SIZE);
  58:             header->next = next;
  59:             header->size = size + HEADER_SIZE;
  60:             header->type = HEAP_BLOCK_USED;
  61:             return ADDR_ADD(header,HEADER_SIZE);
  62:         }
  63:         header = header->next;
  64:     }
  65:     return NULL;
  66: }
  67:  
  68: void free(void* ptr)
  69: {
  70:     //首先找到头部
  71:     heap_header* header = (heap_header*)ADDR_ADD(ptr, -HEADER_SIZE);
  72:  
  73:     //如果头部标志没有被使用
  74:     if (header->type != HEAP_BLOCK_USED)
  75:     {
  76:         return;
  77:     }
  78:     
  79:     //标记
  80:     header->type = HEAP_BLOCK_FREE;
  81:  
  82:     //检查前面一块内存是否空,否则合并
  83:     if (header->prev != NULL && header->prev->type == HEAP_BLOCK_FREE)
  84:     {
  85:         header->prev->next = header->next;
  86:         if (header->next != NULL)
  87:         {
  88:             header->next->prev = header->prev;
  89:         }
  90:  
  91:         header->prev->size += header->size;
  92:         header = header->prev;
  93:     }
  94:  
  95:     //检查后面一块内存是否为空,否则合并
  96:     if (header->next != NULL && header->next->type == HEAP_BLOCK_FREE)
  97:     {
  98:         header->size += header->next->size;
  99:         header->next->next->prev = header;
 100:         header->next = header->next->next;
 101:     }
 102: }
 103:  
 104: int heap_init()
 105: {
 106:     void* base = NULL;
 107:     heap_header* header = NULL;
 108:  
 109:     //初始堆大小默认为32M
 110:     unsigned heap_size = 1024 * 1024 * 32;
 111:  
 112:     //调用VirtualAlloc函数分配
 113:     base = VirtualAlloc(0, heap_size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
 114:     if (base == NULL)
 115:     {
 116:         return 0;
 117:     }
 118:  
 119:     header = (heap_header*)base;
 120:     header->size = heap_size;
 121:     header->type = HEAP_BLOCK_FREE;
 122:     header->next = NULL;
 123:     header->prev = NULL;
 124:  
 125:     list_head = header;
 126:     return 1;
 127: }

posted on 2009-09-29 11:33  乌龟_毛驴  阅读(643)  评论(2编辑  收藏  举报

导航