You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 16:00:17