<@乌龟:>手动实现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: }