最可靠方式是解析/proc/self/status获取VmRSS和VmData:VmRSS为进程物理内存驻留量(KB),VmData近似堆分配总量(KB),但mmap分配不计入VmData。

Linux 下用 /proc/self/status 读取 VmRSS 和 VmData 最可靠
Linux 系统本身不提供标准 C++ 接口获取堆内存总量或驻留量,mallinfo 已废弃且不准,malloc_stats 只打屏不返回数据。最直接有效的方式是解析 /proc/self/status —— 它由内核实时维护,字段稳定、开销低、无需额外权限。
关键字段:
-
VmRSS:当前进程实际驻留在物理内存中的大小(KB),含堆、栈、共享库代码段等,但它是进程级总驻留量,不是纯堆驻留量 -
VmData:数据段大小(KB),近似反映堆分配总量(brk系统调用扩展的匿名映射区),不含mmap分配的大块内存 - 若程序大量使用
mmap(MAP_ANONYMOUS)(如 jemalloc/tcmalloc 默认行为),VmData会严重低估堆总量,此时需配合VmSize或扫描/proc/self/maps
示例读取逻辑:
std::ifstream f("/proc/self/status");
std::string line;
while (std::getline(f, line)) {
if (line.rfind("VmRSS:", 0) == 0) {
long rss_kb = std::stol(line.substr(6));
// rss_kb 单位 KB
} else if (line.rfind("VmData:", 0) == 0) {
long data_kb = std::stol(line.substr(7));
// data_kb 单位 KB
}
}
Windows 下必须用 GetProcessMemoryInfo + GetProcessHeap 组合估算
Windows 没有类似 /proc 的统一视图。GetProcessMemoryInfo 返回 PROCESS_MEMORY_COUNTERS_EX,其中 WorkingSetSize 接近 VmRSS,PrivateUsage 更准确反映进程独占物理内存;但它不区分堆/栈/代码,纯属进程维度。
立即学习“C++免费学习笔记(深入)”;
要估算堆分配总量,得手动遍历所有堆(包括 CRT 默认堆和显式 HeapCreate 的堆):
- 调用
GetProcessHeaps获取堆句柄数组 - 对每个句柄调用
HeapWalk遍历块,累加lpbusy->dwBlockSize(仅限已分配块) - 注意:
HeapWalk是同步操作,多线程下需暂停其他线程或接受竞态结果;且无法统计通过VirtualAlloc直接申请的大内存(绕过堆管理器) - CRT 的 malloc 在 Windows 默认使用进程默认堆,但启用
/MT或自定义分配器后可能脱离该路径
mallinfo 和 malloc_usable_size 为什么不能用
mallinfo 在 glibc 2.33+ 已标记为废弃,返回值语义模糊:uordblks 是“已分配字节数”,但只统计 brk 区域,忽略所有 mmap 分配;且其结构体字段在不同 glibc 版本中含义变动,比如 fordblks 在某些版本里包含未合并的空闲 chunk,导致数值跳变。
malloc_usable_size 只能查单个指针对应内存块的**实际可用大小**(含 padding),无法汇总全局堆状态;而且它不适用于 mmap 分配的内存(glibc 中返回 0)。
常见误用场景:
- 循环遍历所有已分配指针并累加
malloc_usable_size→ 不可行:你根本拿不到所有指针地址 - 把
mallinfo().uordblks当作“当前堆用量” → 在启用了 mmap threshold(默认 128KB)的程序中,大对象全走 mmap,uordblks几乎为 0
跨平台封装要注意的三个硬伤
任何试图写一个“跨平台 get_heap_usage()” 的封装,都会撞上这三点本质差异:
- Linux
VmData和 WindowsHeapWalk结果不可比:前者是sbrk增量,后者是各堆手动能枚举块之和,二者覆盖范围不一致 - 驻留量(RSS / WorkingSet)永远只是近似值:Linux kernel 会延迟回收 page,Windows 的 Working Set 会受系统内存压力动态收缩,两次相邻调用结果可能差几 MB
- 没有“当前堆驻留量”这个精确概念:堆内存页可能被 swap out、被共享、被 mmap 映射为文件后备,所谓“驻留”本身依赖于瞬时系统状态,工具只能采样,不能精确定义
如果真要监控,建议在 Linux 用 /proc/self/status 定期采样,在 Windows 用 GetProcessMemoryInfo + 定期 HeapWalk(注意线程安全),并明确文档里写清:“此值为估算,反映内核/系统当前视角下的内存占用”。


















