自定义malloc函数中指针字节偏移异常问题排查
自定义malloc实现中的地址偏移错误问题
在实现自定义malloc函数时,出现了内存块偏移量远超预期的问题:分配4字节int时,预期空闲块从偏移20的位置开始,但实际却在320位置。以下是具体实现细节和运行现象:
堆初始化逻辑
- 使用
sysconf(_SC_PAGESIZE)获取内存页大小存入g_pagesize - 通过
sbrk(g_pagesize)扩展堆并记录起始地址g_start - 调用
sbrk(0)记录堆结束地址g_end
内存块结构
typedef struct header { size_t m_size; struct header *m_next; } header_st;
初始化时g_free指向堆起始地址,设置其m_size为g_pagesize - sizeof(header_st),g_used初始化为NULL。
分配逻辑(问题代码)
void *IR_malloc(size_t bytes_size) { if (g_active == false) IR_init(); size_t block_size = sizeof(header_st) + bytes_size; printf("Block size: %lu\n", block_size); header_st *blk = g_free; g_free += block_size; // 错误的指针算术 blk->m_size = bytes_size; blk->m_next = g_used; g_used = blk; return g_used + sizeof(header_st); // 错误的返回地址计算 }
运行现象
第一次分配4字节后,空闲块偏移量为320而非预期的20,后续分配的偏移量也持续异常增大。
核心错误分析
指针算术错误:
对header_st*类型指针做加法时,编译器会自动乘以sizeof(header_st)的大小。比如g_free += block_size实际等价于g_free = (header_st*)((char*)g_free + block_size * sizeof(header_st)),直接导致地址被过度偏移。
同样,返回地址g_used + sizeof(header_st)也犯了相同错误,必须用字符指针来做字节级别的偏移计算。空闲块大小未更新:
分配内存后没有更新空闲块的m_size,导致后续空闲块大小显示为0,无法正确管理剩余内存。
修复后的代码
修正后的IR_malloc函数
void *IR_malloc(size_t bytes_size) { if (g_active == false) IR_init(); size_t block_size = sizeof(header_st) + bytes_size; printf("Block size: %lu\n", block_size); // 用char*做字节级偏移,避免指针算术的自动缩放 header_st *blk = g_free; g_free = (header_st*)((char*)g_free + block_size); // 更新空闲块的剩余大小 g_free->m_size = blk->m_size - bytes_size - sizeof(header_st); g_free->m_next = NULL; blk->m_size = bytes_size; blk->m_next = g_used; g_used = blk; // 返回数据区地址:跳过头部,用char*做字节偏移 return (char*)blk + sizeof(header_st); }
修复后的运行验证
第一次分配4字节后,空闲块会从偏移20的位置开始,后续分配也会按连续内存的预期进行,空闲块大小也会正确更新为剩余可用内存。
内容的提问来源于stack exchange,提问作者Jesper
相关产品推荐
相关产品推荐

