linux下用mallinfo或malloc_stats可获取堆分配总量(arena+hblkhd)和用户数据占用量(uordblks),但二者均不反映真实驻留内存(rss),也不统计mmap分配;真正驻留量应读取/proc/self/status中的vmrss字段。

Linux 下用 mallinfo 或 malloc_stats 看堆分配总量,但注意它不反映驻留内存
mallinfo 是 glibc 提供的接口,返回一个 struct mallinfo,其中 arena + hblkhd 近似当前向系统申请的总堆内存(即“分配总量”),uordblks 是已分配未释放的用户数据块字节数(常被误当作“驻留量”,实际不是)。但它不区分物理页是否被换出、是否被内核回收,也不统计 mmap 分配的内存(如大对象走 mmap 时就完全不计入)。调用前无需初始化,但结果是快照,且多线程下无原子保证。
更轻量的调试方式是调用 malloc_stats(),它直接打印到 stderr,包含 system bytes(向系统申请总量)和 in use bytes(当前用户占用),适合快速验证。但无法编程读取,仅用于诊断。
示例片段:
#include <malloc.h> #include <iostream> struct mallinfo mi = mallinfo(); std::cout <h3>/proc/self/statm 和 /proc/self/status 能查驻留内存(RSS)与虚拟内存(VSZ)</h3> <p>Linux 进程的真正驻留物理内存(RSS)必须查 <code>/proc/self/statm</code> —— 第二个字段是 RSS 页数,乘以 <code>getpagesize()</code> 得字节数;第一个字段是总虚拟内存页数(VSZ)。它反映的是内核视角的物理页占用,含代码段、堆、栈、共享库等所有驻留页,不单是堆。</p> <p><code>/proc/self/status</code> 更易读:<code>VmRSS:</code> 行是 RSS 字节数,<code>VmSize:</code> 是 VSZ,<code>VmData:</code> 接近堆+数据段的粗略估计(但含 BSS、brk 扩展部分,不含 mmap 堆)。注意:这些值有延迟,内核不会实时更新,且受内存压缩、THP、swap 等影响。</p><div class="aritcle_card flexRow artxards"> <div class="artcardd flexRow"> <a class="aritcle_card_img" rel="nofollow" href="/xiazai/skill5502" title="C++ Code Review Master"><img src="https://img.php.cn/upload/skill/000/000/081/179051228971575.jpg" alt="C++ Code Review Master" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a> <div class="aritcle_card_info flexColumn"> <a rel="nofollow" href="/xiazai/skill5502" title="C++ Code Review Master" class="overflowclass">C++ Code Review Master</a> <p class="overflowclass">组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。</p> </div> <a rel="nofollow" href="/xiazai/skill5502" title="C++ Code Review Master" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span> </a> </div> </div> <p>读取要点:</p> <ul> <li>需用 <code>std::ifstream</code> 或 <code>fopen</code> 打开 <code>/proc/self/status</code>,逐行扫描匹配 <code>VmRSS:</code> </li> <li>避免频繁读取(/proc 是伪文件系统,但仍有开销),生产环境建议采样间隔 ≥100ms</li> <li>容器中若挂载了 <code>procfs</code> 的子集,可能缺失字段,需 fallback 到 <code>statm</code> </li> </ul> <h3>要统计“释放次数”或“分配频次”,得自己 hook <code>malloc</code>/<code>free</code>,glibc 不提供内置计数器</h3> <p>glibc 没有暴露分配/释放调用次数的接口。想统计释放次数、平均分配大小、高频分配栈等,唯一可靠方式是 LD_PRELOAD hook 或使用 <code>__malloc_hook</code> 等(已废弃)或改用 <code>malloc_usable_size</code> 配合自定义分配器。</p> <p>推荐做法:在程序启动时用 <code>malloc_hook</code> 替换(仅限旧版 glibc),或更稳妥地用 <code>LD_PRELOAD</code> 注入一个包装 <code>malloc</code>/<code>free</code> 的共享库。关键点:</p> <ul> <li>hook 函数里必须用 <code>__libc_malloc</code> 和 <code>__libc_free</code> 调用原函数,否则递归崩溃</li> <li>计数器变量要用 <code>static __thread</code> 或原子操作,避免多线程竞争</li> <li>不要在 hook 里做 I/O 或锁重操作,否则严重拖慢内存路径</li> <li>C++ new/delete 默认调用 malloc/free,所以也会被覆盖;但 <code>operator new(std::nothrow)</code> 或定位 new 不经过此路径</li> </ul> <h3>别混淆“堆分配总量”和“进程驻留内存”,它们由不同机制管理</h3> <p>堆分配总量(如 <code>mallinfo.arena + hblkhd</code>)只是 malloc 实现层向上申请的内存块累计值;而 RSS(<code>/proc/self/statm</code> 第二列)是内核维护的物理页映射总数。两者差异极大:malloc 释放后,内存常被保留在 arena 里供复用,RSS 不下降;大量小对象释放后若没触发 <code>brk</code> 回退或 <code>madvise(MADV_DONTNEED)</code>,RSS 就一直虚高。</p> <p>真正影响 OOM 的是 RSS,不是 malloc 统计值;监控告警应优先看 <code>VmRSS</code>,而不是自己累加 <code>malloc</code> 大小。另外,如果用了 jemalloc/tcmalloc,<code>mallinfo</code> 完全失效,必须用对应库的 API(如 <code>malloc_stats_print</code>)或 <code>/proc</code>。</p></iostream></malloc.h>
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










