Linux下VmPeak字段记录进程虚拟内存峰值,单位KB,比getrusage()更准确;需配合RLIMIT_AS判断是否触限;Windows无等价API,PeakPagefileUsage仅为粗略代理。

Linux下用/proc/self/status读取VmPeak最直接
Linux进程的虚拟内存峰值(即历史最大驻留虚拟地址空间)就记录在/proc/self/status里,字段是VmPeak,单位KB。它比getrusage()更准——后者只报告RSS峰值,且部分内核版本不更新RSS字段。
实操建议:
立即学习“C++免费学习笔记(深入)”;
- 用
std::ifstream打开/proc/self/status,逐行扫描以VmPeak:开头的行 - 注意字段后可能有空格或制表符,用
std::istringstream提取数值比sscanf更安全 - 不要依赖
VmSize——它是当前虚拟内存大小,不是峰值;VmPeak才是你要的硬指标 - 该文件每秒可安全读多次,但频繁轮询(如每毫秒)会增加I/O开销,建议仅在关键检查点(如单元测试结束、模块卸载前)读一次
获取虚拟内存限额要用getrlimit(RLIMIT_AS, &rlim)
RLIMIT_AS(address space limit)控制进程能分配的虚拟内存总量,单位是字节。它和VmPeak配合看才有意义:比如VmPeak=2.1GB而rlimit.as_cur=2GB,说明程序已触顶,下次mmap或new大概率std::bad_alloc。
实操建议:
立即学习“C++免费学习笔记(深入)”;
- 调用前确保
rlimit结构体清零:struct rlimit rlim{};,否则未初始化字段可能引发误判 -
rlim.rlim_cur是软限制(可被setrlimit提升),rlim.rlim_max是硬限制(需root权限才能提) - 若
rlim.rlim_cur == RLIM_INFINITY,表示无硬性限制,但物理内存或swap仍会最终制约——别当成“无限可用” - 注意glibc 2.34+对
RLIMIT_AS的处理更严格,某些容器环境(如Docker默认)会设为非无穷值,务必实测
Windows下没有等价VmPeak,得用GetProcessMemoryInfo
Windows没有暴露虚拟内存历史峰值的API,PROCESS_MEMORY_COUNTERS_EX里的PeakPagefileUsage和PeakWorkingSetSize分别对应页文件峰值和工作集峰值,都不是你想要的“虚拟地址空间峰值”。真正接近的是VirtualAlloc手动跟踪,但成本高、易漏。
实操建议:
立即学习“C++免费学习笔记(深入)”;
- 用
GetProcessMemoryInfo读PeakPagefileUsage作为粗略代理——它反映进程曾占用的最大页文件量,与虚拟内存使用强相关,但不等于VmPeak - 若必须精确统计,只能在每次
VirtualAlloc/VirtualFree时维护一个全局累加器,记录累计分配/释放差值的最大值 - 注意
VirtualQuery可遍历所有内存区域,但无法回溯历史,只能查当前状态,不能替代峰值统计 - MinGW或MSVC编译时需链接
psapi.lib,否则GetProcessMemoryInfo链接失败
跨平台封装要注意size_t和单位换算陷阱
Linux返回KB,Windows返回字节,rlimit是字节,VmPeak是KB——混在一起极易出错。统一转成字节再比较是最稳妥的做法。
实操建议:
立即学习“C++免费学习笔记(深入)”;
- 定义枚举
mem_unit_t { BYTE, KB, MB },所有读取函数内部完成单位归一化 - 避免用
sizeof(size_t)判断平台位数来决定是否用uint64_t——getrlimit在x86_64上返回rlim_t,它可能是long(8字节)或unsigned long long(取决于glibc版本) - 读
/proc/self/status时,如果VmPeak: 12345678 kB,别用atoi——超2GB会溢出,改用std::stoll并乘1024 - Windows下
PeakPagefileUsage最大值可能达TB级,DWORD肯定不够,必须用SIZE_T或uint64_t
VmPeak和RLIMIT_AS的组合判断比单看一个值有用得多;而Windows端的“峰值”本质是妥协方案,真要监控就得自己埋点。


















