C语言实现my_malloc与my_free时prologue和epilogue的创建方法
你给出的代码存在多处错误,无法正常实现需求:
sbrk()需要传入要申请的内存增量作为参数,无参调用不符合函数定义,你要申请4096字节堆空间应该写sbrk(4096)- C标准不允许对
void*类型直接做算术运算,heapspace += 8的写法在部分编译器下会直接报错 - 该逻辑和创建epilogue没有任何关系,整体的初始化逻辑完全缺失
接下来是正确的prologue、epilogue实现和对齐处理方案:
基础约定
我们默认采用8字节对齐规则,块头(header)和块尾(footer)各占8字节,低3位用来存储块的分配状态,其余高位存储整个块(header+数据区+footer)的总大小。
初始化堆(首次申请4096字节时的处理)
首次调用sbrk(4096)申请到整页空间后,按顺序构造三个部分:
- prologue块(序言块)
是一个固定大小16字节的已分配dummy块,不需要存储实际数据,作用是避免空闲块合并时的边界判断:- 偏移0字节处写header:值为
0x10 | 0x1,代表块大小16字节,已分配 - 偏移8字节处写footer:值和header完全相同
- 偏移0字节处写header:值为
- 初始空闲块
占用除去prologue和epilogue之外的所有空间,计算方式为 4096 - 16(prologue大小) - 8(epilogue大小)= 4072字节:- 偏移16字节处写header:值为
4072 | 0x0,代表块大小4072字节,未分配 - 偏移16 + 4072 - 8 字节处写footer:值和该块header完全相同
- 偏移16字节处写header:值为
- epilogue块(尾声块)
是一个只有header的特殊块,作用是标记堆的末尾,遍历块时遇到大小为0的块即可终止遍历:- 偏移4096 - 8字节处写header:值为
0x0 | 0x1,代表块大小0,已分配
- 偏移4096 - 8字节处写header:值为
构造完成后,堆的起始地址会固定指向prologue块的起始位置,后续分配的块从prologue之后的空闲块开始划分。
对齐处理规则
每次收到用户的分配请求时,先将用户申请的大小向上对齐到8的倍数,再加上header和footer的总大小16字节,得到实际需要分配的块总大小,保证返回给用户的指针地址是8字节对齐的。
简单的my_malloc核心逻辑示例
// 先定义对齐掩码,这里按8字节对齐 #define ALIGN_MASK 0x7 #define ALIGN(size) (((size) + ALIGN_MASK) & ~ALIGN_MASK) #define PACK(size, alloc) ((size) | (alloc)) void* my_malloc(size_t size) { // 首次分配时先初始化堆 static int heap_initialized = 0; static char* heap_start; if (!heap_initialized) { heap_start = sbrk(4096); // 构造prologue *(size_t*)(heap_start) = PACK(16, 1); *(size_t*)(heap_start + 8) = PACK(16, 1); // 构造初始空闲块 size_t free_size = 4096 - 16 - 8; *(size_t*)(heap_start + 16) = PACK(free_size, 0); *(size_t*)(heap_start + 16 + free_size - 8) = PACK(free_size, 0); // 构造epilogue *(size_t*)(heap_start + 4096 - 8) = PACK(0, 1); heap_initialized = 1; } // 对齐用户申请的大小 size_t adjust_size = ALIGN(size) + 16; // 加上header和footer的16字节 // 遍历空闲块找适配的块,此处省略首次适配/最佳适配逻辑 // 找到合适的块后划分、标记分配,返回用户数据区指针(header + 8的位置) // ... 省略剩余分配逻辑 }
内容的提问来源于stack exchange,提问作者randomNameGenerator
相关产品推荐
相关产品推荐

