linux下最可靠方式是解析/proc/self/status中的vmrss(当前驻留物理内存,kb)和vmsize(虚拟地址空间大小,kb);mallinfo或malloc_info可获取glibc堆内部状态但多线程不准用mallinfo;windows无等价api,仅能通过getprocessmemoryinfo或crt debug heap辅助分析;精确统计分配/释放总量必须自行hook malloc/free。

Linux 下用 /proc/self/status 读取进程内存统计(最可靠)
标准 C++ 没有跨平台接口获取堆分配总量或释放总量,malloc 和 new 的底层计数不对外暴露。Linux 下唯一稳定、无需侵入式 hook 的方式是解析 /proc/self/status 中的字段:VmRSS(当前驻留物理内存)、VmSize(虚拟地址空间大小),但注意:它们不等于“堆分配量”,而是整个进程的内存视图。
关键字段含义:
-
VmRSS:当前驻留在物理内存中的页数(含堆、栈、共享库等),单位 KB —— 这是你能拿到的最接近“当前驻留量”的值 -
VmSize:进程虚拟地址空间总大小(含未分配的 mmap 区域、预留空间),单位 KB —— 不反映实际堆使用,但可辅助判断是否异常膨胀 -
MMU无关,Heap字段在/proc/self/status中并不存在;glibc 的mallinfo或malloc_stats输出的是 malloc arena 内部状态,但不包含已free但未返还 OS 的内存,且多线程下不准
用 mallinfo 或 malloc_info 获取 glibc 堆内部统计(仅限 Linux + glibc)
如果你必须知道 malloc 管理器视角下的“已分配”“已释放但未归还”等细节,mallinfo 是传统接口,但已被标记为 deprecated;推荐改用 malloc_info(0, fd) 输出 XML,再解析。
示例要点:
-
mallinfo().uordblks:当前已分配(used)的字节数(含 malloc 分配但未 free 的块) -
mallinfo().fordblks:当前空闲(free)但仍在 malloc arena 中的字节数(即已free,但未brk或mmap归还 OS) -
malloc_info(0, fd)输出包含<heap></heap>节点,其中total和system属性分别对应 arena 总用量和向 OS 申请的总量(单位字节) - 多线程下
mallinfo只返回主 arena 数据,malloc_info才包含所有 arenas,但需自己解析 XML
Windows 下只能靠 GetProcessMemoryInfo + CRT Debug Heap(无释放总量)
Windows 没有等价于 mallinfo 的公开 API。GetProcessMemoryInfo 返回的 PROCESS_MEMORY_COUNTERS_EX.PrivateUsage 类似 VmRSS,是进程私有工作集大小(KB),但不含共享内存;它也不区分堆/栈/代码段。
若使用 MSVC CRT 的 debug heap(仅 debug build),可启用 _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF) 并调用 _CrtMemState 捕获某时刻堆快照,但仅支持对比差值,无法获得“释放总量”这种累积计数 —— CRT 不记录每次 free 的字节数。
常见误判:
- 把
PrivateUsage当作“堆分配总量” → 错,它含所有私有内存(包括大块VirtualAlloc分配) - 以为
_CrtDumpMemoryLeaks()能输出历史释放量 → 它只报告未释放块,不统计已释放行为
想真正统计“分配/释放总量”,必须自己 hook malloc/free(跨平台可行但有代价)
如果业务确实需要精确的累计分配字节数、释放字节数、当前活跃字节数,唯一办法是拦截内存分配函数。POSIX 下可用 LD_PRELOAD 替换 malloc/free/realloc;Windows 下可用 Detours 或 MSVC 的 _malloc_dbg 钩子。
实操建议:
- 不要直接 patch libc,用
__wrap_malloc+--wrap=malloc链接选项更安全(GCC) - 全局原子变量计数:
std::atomic_size_t total_alloc{0}, total_free{0},在 wrapper 中增减 - 注意
realloc既可能释放旧块又分配新块,需拆解为free+malloc逻辑处理 - 性能影响显著:每个分配都带原子操作,高频小对象场景可能降速 2–5×;生产环境慎用,仅用于诊断或测试
没有银弹:所谓“堆分配总量”本身定义模糊——是指 malloc 调用次数乘以参数?还是指所有 malloc 返回地址的生命周期内最大同时驻留?不同需求得选不同方案。别指望一个函数调用就拿到全部答案。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











