Linux下/proc/self/statm第一列是虚拟内存总页数,乘以getpagesize()得字节数;Windows用GetProcessMemoryInfo获取PeakPagefileUsage(提交内存峰值);跨平台需注意定义差异、32位溢出及ASLR影响。

Linux下用/proc/self/statm读取虚拟内存页数
Linux进程的虚拟内存总量(即VIRT)在/proc/self/statm中以页为单位存储,第一列就是总虚拟内存页数。注意这不是物理内存,也不含共享库重复计数,而是mmap、brk、stack等所有映射区域的总和。
实操建议:
立即学习“C++免费学习笔记(深入)”;
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
- 打开
/proc/self/statm文件,用std::ifstream读取一行,按空格分割,取第一个字段 - 将该值乘以
getpagesize()得到字节数(通常为4096) - 不要用
/proc/self/status里的VmSize字段——它虽是可读字符串,但解析更慢,且单位是KB,需额外转换 - 如果程序被
ptrace或沙箱限制(如某些容器),/proc可能不可读,应加errno检查
Windows下调用GetProcessMemoryInfo获取PeakPagefileUsage
Windows没有直接对应“虚拟内存总量”的单一字段,PROCESS_MEMORY_COUNTERS_EX结构体中PeakPagefileUsage最接近:它表示进程生命周期内最大提交内存(commit size),即虚拟地址空间中已保留+已提交部分的峰值,单位是字节。
实操建议:
立即学习“C++免费学习笔记(深入)”;
- 必须链接
psapi.lib,并调用GetProcessMemoryInfo(GetCurrentProcess(), &pmc, sizeof(pmc)) -
pmc.PagefileUsage是当前值,pmc.PeakPagefileUsage才是历史最大值,多数场景后者更有参考意义 - 注意
PROCESS_MEMORY_COUNTERS_EX需定义_WIN32_WINNT≥ 0x0501,否则结构体不完整 - 该值不含未提交的保留区(比如
VirtualAlloc(..., MEM_RESERVE)但没MEM_COMMIT的部分),所以可能略小于VirtualQuery遍历结果总和
跨平台封装要注意的三个陷阱
写通用函数时,别假设“虚拟内存”有统一定义——Linux的statm包含所有映射,Windows的PagefileUsage只计提交部分,macOS甚至没等价API(得用task_info + task_vm_info,且需要特权)。
关键差异点:
- Linux返回的是瞬时快照,Windows返回的是峰值;若需实时值,Windows只能用
PagefileUsage,但它不含尚未写入页面文件的脏页 - 32位程序在64位系统上,Windows的
GetProcessMemoryInfo仍只返回32位计数器,可能溢出;应优先用GetProcessMemoryInfo的Ex版本,并检查sizeof(SIZE_T) - 不要用
mallinfo或malloc_stats——它们只反映堆分配器管理的内存,漏掉mmap、共享库、线程栈等大部分虚拟内存
调试时发现数值异常?先查mmap标志和ASLR
如果读到的虚拟内存远大于预期(比如几GB),大概率是程序用了大块mmap(MAP_ANONYMOUS | MAP_NORESERVE),或者启用了ASLR导致地址空间碎片化——这些都会计入statm或PagefileUsage,但实际不占用物理资源。
验证方法:
- Linux下运行
cat /proc/self/maps | wc -l看映射段数量,再用awk '{sum += $3-$1} END {print sum}' /proc/self/maps粗算总映射大小 - Windows下用
vmmap(Sysinternals工具)对比“Commit Size”和“Reserved”两列 - 确认是否调用了
mmap或VirtualAlloc时传了MAP_NORESERVE或MEM_RESERVE——这类预留不立即消耗页表项,但会计入总量
虚拟内存总量本身不反映压力,真正影响性能的是RSS或Working Set。别把statm第一列当OOM依据,它只是地址空间使用上限的粗略指标。

















