Linux下VmHWM表示进程自启动以来虚拟内存地址空间峰值(单位KB),含brk和mmap区域,非物理内存RSS;Windows用GetProcessMemoryInfo的PeakPagefileUsage近似,macOS无等效接口。

Linux 下用 /proc/self/status 读取 VmHWM
Linux 内核会在进程的 /proc/self/status 文件中记录当前进程的内存统计,其中 VmHWM(Virtual Memory High Water Mark)字段就是虚拟内存占用的峰值,单位是 KB。它反映的是自进程启动以来,brk 和 mmap 区域合计达到过的最大虚拟地址空间大小。
注意:这不是 RSS 或实际物理内存使用量,而是虚拟内存地址空间的峰值上限 —— 比如你 mmap 了 1GB 文件但只访问了一页,VmHWM 仍会包含这 1GB。
实操建议:
- 打开
/proc/self/status,逐行读取直到找到以VmHWM:开头的行 - 用
sscanf提取数字部分,别忘了跳过空格和单位(如"kB") - 该值在 fork 后子进程独立计数,不继承父进程的峰值
- 频繁轮询无意义 ——
VmHWM只增不减,且更新非实时,依赖内核统计时机
Windows 下调用 GetProcessMemoryInfo 获取 PeakPagefileUsage
Windows 没有直接对应 VmHWM 的指标,最接近的是 PROCESS_MEMORY_COUNTERS_EX::PeakPagefileUsage,它表示进程生命周期中页文件(pagefile)占用的峰值字节数 —— 这个值约等于虚拟内存峰值(因为 Windows 虚拟内存 = 物理内存 + 页文件预留),但不含未提交的保留地址空间(如仅 VirtualAlloc(MEM_RESERVE) 未 COMMIT 的区域)。
立即学习“C++免费学习笔记(深入)”;
实操建议:
- 需链接
psapi.lib,并确保定义_WIN32_WINNT≥ 0x0501(即 XP+) - 必须用
PROCESS_MEMORY_COUNTERS_EX结构体,普通PROCESS_MEMORY_COUNTERS不含PeakPagefileUsage - 调用前检查
GetProcessMemoryInfo返回值,失败时GetLastError()常为ERROR_ACCESS_DENIED(尤其在低完整性进程查高完整性进程时) - 该值不会自动清零,重启进程才会重置
跨平台封装要注意的兼容性陷阱
没有标准 C++ API 能跨平台获取虚拟内存峰值,强行抽象容易掩盖关键差异。比如:
- Linux
VmHWM包含所有mmap区域(含 MAP_ANONYMOUS、MAP_SHARED、文件映射),而 WindowsPeakPagefileUsage不计入未提交的保留区,也不含共享内存对象的全局占用 - 两者单位不同:Linux 是 KB,Windows 是字节,转换时容易漏掉乘除
- macOS 完全不提供等效接口 ——
task_info只有phys_footprint(RSS 类似值),没有虚拟内存峰值;vm_statistics64也无进程级 HWM 字段 - 容器环境(如 Docker)中,
/proc/self/status仍有效,但值受 cgroup memory limit 影响 ——VmHWM可能远低于宿主机限制,却仍可能触发 OOM killer
为什么不用 mallinfo 或 malloc_stats
这两个是 glibc 的堆管理器内部统计,只覆盖 malloc/free 管理的 heap 区域,完全不包括:mmap 分配的大块内存、静态/全局数据段、栈空间、共享库代码段。实际程序的虚拟内存峰值往往由 mmap 主导(例如加载大模型权重、内存映射日志文件),所以它们严重低估真实值。
实操判断:
- 若你的程序大量使用
mmap、std::filesystem::mapped_file或第三方库(如 OpenCV 的内存映射 I/O),mallinfo几乎无参考价值 -
malloc_stats输出到 stderr,无法编程读取,且格式不稳定(glibc 版本间有差异) - 即使只用
new,现代 libc++/MSVC STL 也可能在大分配时直走mmap,绕过 malloc arena
真正需要虚拟内存峰值时,别绕弯 —— Linux 查 /proc/self/status,Windows 调 GetProcessMemoryInfo,其他系统就得接受不可得。这个值本身就不“标准”,硬统一反而误导。


















