glibc中free()未清除prev_in_use位问题咨询
关于glibc 2.19中free()行为的疑问
环境信息
- 64位Linux系统
- glibc版本:
ldd (Ubuntu EGLIBC 2.19-0ubuntu6.15) 2.19
测试代码
int main (int argc , char** argv){ char *first , *second; first = malloc(16); second = malloc(16); free(first); free(second); }
观察到的现象
根据glibc内存管理的知识,调用free()时应该会清除下一个相邻内存块的prev_in_use位,同时在该内存块的prev_size字段写入当前释放块的大小。但第一次调用free(first)后,通过gdb查看内存区域:
gdb-peda$ x/20gx 0x602010-16 0x602000: 0x0000000000000000 0x0000000000000021 0x602010: 0x0000000000000000 0x0000000000000000 0x602020: 0x0000000000000000 0x0000000000000021 0x602030: 0x0000000000000000 0x0000000000000000 0x602040: 0x0000000000000000 0x0000000000020fc1 0x602050: 0x0000000000000000 0x0000000000000000
发现既未清除下一个内存块的prev_in_use位,也未在其prev_size字段写入释放块的大小。
原因分析
这是因为当释放的块处于fastbin中时,glibc不会修改下一个块的prev_in_use位和prev_size字段。
在glibc 2.19中,malloc(16)分配的块属于fastbin范畴(fastbin用于管理小尺寸内存块,默认阈值是64字节)。当释放这类块时,glibc会直接将其放入对应的fastbin链表,不会进行合并操作,也就不会去修改下一个相邻块的相关字段——这些字段的修改只有在块被放入unsorted bin或者进行合并时才会触发。
你可以验证这一点:如果将分配的内存大小改为超过fastbin阈值(比如80字节),再调用free(),就能观察到你预期的修改下一个块prev_in_use位和prev_size的行为。
另外,从你gdb输出的内存信息来看,0x602020位置的块头部是0x0000000000000021,其中最后一位是1(prev_in_use位),说明该块的前一个块被标记为正在使用,这符合fastbin释放时的行为——因为fastbin中的块不会被合并,所以glibc不会修改下一个块的这个标记位。
内容的提问来源于stack exchange,提问作者Muhammad Jamshaid
相关产品推荐
相关产品推荐

