Free底层是怎么释放内存的

free 并不是把进程地址空间里的那一页直接"还"给操作系统,而是在用户态的堆管理器(glibc/ptmalloc、Windows CRT、jemalloc、tcmalloc 等)里完成一次记账操作。下面以 glibc 默认的 ptmalloc2 为例,把一次 free(ptr) 的完整链路拆开说明,其他实现思路大同小异。

1、先做"合法性"检查

如果 ptr == NULL,立即返回。

把指针往回偏移一个固定长度,拿到 chunk 头(下面会讲头里有什么)。

检查该 chunk 的魔数、对齐位、是否属于当前 arena 等,若发现异常直接 abort(经典的 "free(): invalid pointer" 报错就来自这里)。

2、怎么"知道"要释放多大

malloc 返回给用户的地址 并不是 真正从系统要到的起始地址,而是 紧接在头部后面的用户区。头部里保存了本次分配的大小(以及标志位、魔数等)。

free 时把传入的指针往前挪 8~16 B 就能拿到这个 "malloc_chunk" 头,从而读出 chunk_size [⁴][⁷]。

3、放进哪个"桶"------空闲链表

ptmalloc 把空闲块按大小分两类管理:

≤ 64 B 的精确大小 → fastbin[](LIFO,单向链表,不回填中央堆)。

65 B ~ 128 KB → small/large bin(双向链表,按大小排序)。

更大 → top chunk 直接 mmap,释放时用 munmap 还给内核。

根据大小把 chunk 链到对应 bin 里,并置标志位 IS_INUSE=0

4、立即合并(backward & forward coalesce)

检查物理相邻的前后两个 chunk 是否也是空闲:

是 → 把它们从各自 bin 中摘下,合并成一个更大的 chunk,再挂到对应的大 bin 里。

否 → 直接把自己挂进去。

这一步用来缓解外部碎片

5、是否"还"给操作系统

只有当 top chunk(堆顶最后一块空闲)大小超过 128 KB 时,ptmalloc 才会通过 brk(-size) 把尾部缩减,真正归还给内核;否则仍留在进程堆内,供下次 malloc 复用 [⁵][⁶]。

因此大多数 free 只是用户态记账,不会立刻体现为系统内存下降。

6、多线程场景

每个线程默认先绑定一个 arena(内存池),free 时若发现该 chunk 属于别的 arena,会把内存"搬家"到对应 arena 的空闲链表,再加互斥锁,防止并发破坏链表

所以,free 的"释放"本质是 "把一块内存从占用状态标成空闲,并挂进分配器的空闲链表";只有堆顶出现足够大的连续空闲块时,才会通过系统调用真正缩小进程地址空间。

Q: 是怎么找到chuck_size的?

相关推荐
2601_9491465311 分钟前
C语言语音通知接口接入教程:如何使用C语言直接调用语音预警API
c语言·开发语言
wdfk_prog1 小时前
[Linux]学习笔记系列 -- [drivers][input]input
linux·笔记·学习
盟接之桥1 小时前
盟接之桥说制造:引流品 × 利润品,全球电商平台高效产品组合策略(供讨论)
大数据·linux·服务器·网络·人工智能·制造
忆~遂愿2 小时前
ops-cv 算子库深度解析:面向视觉任务的硬件优化与数据布局(NCHW/NHWC)策略
java·大数据·linux·人工智能
湘-枫叶情缘2 小时前
1990:种下那棵不落叶的树-第6集 圆明园的对话
linux·系统架构
知南x2 小时前
【Ascend C系列课程(高级)】(1) 算子调试+调优
c语言·开发语言
Fcy6483 小时前
Linux下 进程(一)(冯诺依曼体系、操作系统、进程基本概念与基本操作)
linux·运维·服务器·进程
袁袁袁袁满3 小时前
Linux怎么查看最新下载的文件
linux·运维·服务器
代码游侠3 小时前
学习笔记——设备树基础
linux·运维·开发语言·单片机·算法
Gary Studio3 小时前
rk芯片驱动编写
linux·学习