free 掉的内存去哪了?跨线程内存漂移与多 Arena 锁竞争的底层反常识

free 掉的内存去哪了?跨线程内存漂移与多 Arena 锁竞争的底层反常识

1. free 干净了,RSS 为什么纹丝不动?

C++ 高并发推理服务在经历夜间批处理后突发 OOM 崩溃。排查监控发现:服务在高峰期临时分配了约 1.2GB 的图像特征 Buffer,计算完成后代码中早已对全部指针执行了free()。按 C/C++ 内存模型的物理直觉,进程的物理内存占用(RSS, Resident Set Size)应当随之滑落 1.2GB。

然而在 Grafana 面板上,RSS 在微跌 50MB 后便死死固定在 14.55GB 的高位,拉出一条平直的水平线。检查/proc/[pid]/smaps_rollupPrivate_Dirty页大小毫无收缩;Valgrind 报0 bytes leaked,ASan 静默无声,Heaptrack 抓不到任何堆增长;代码 Review 确认没有任何未释放的悬挂指针(Dangling Pointer)。

明明free()掉了全部对象,为什么操作系统内核依然认为进程持有这些物理页?

内存并没有泄露,但它也并未归还给 Linux 内核——它被截留在用户态应用程序与操作系统内核之间的“中间层”:glibc ptmalloc(基于 Doug Lea malloc 的多线程改进版,源码位于glibc/malloc/malloc.c)。

1.1free()的物理真相:控