linux下读取虚拟内存大小应使用/proc/self/statm获取首字段页数并乘以getpagesize(),windows下用getprocessmemoryinfo的pagefileusage字段;二者不可统一抽象,且需注意mmap和共享内存的影响。

Linux 下用 /proc/self/statm 读取虚拟内存大小
Linux 系统中,/proc/self/statm 是最轻量、最直接的方式——它不依赖 glibc 扩展或额外权限,且只返回空格分隔的 7 个数字,其中第一个就是进程的总虚拟内存页数(单位是页,通常为 4KB)。
常见错误是误读 /proc/self/status 中的 VmSize 字段:虽然可读性好,但需逐行解析字符串,容易因格式变动(如多空格、字段顺序微调)出错;而 statm 是稳定二进制友好的接口,内核保证字段位置不变。
实操建议:
- 用
std::ifstream打开/proc/self/statm,读取第一整数即可,无需字符串查找 - 记得乘以
getpagesize()转为字节,不要硬编码 4096 —— 少数系统(如某些嵌入式配置)页大小可能不同 - 如果读取失败(比如容器环境挂载了精简版 procfs),应 fallback 到
sysconf(_SC_PAGESIZE)+getrusage()的近似值,但注意getrusage(RUSAGE_SELF, &ru)的ru_maxrss是常驻集(RSS),不是虚拟内存
Windows 下用 GetProcessMemoryInfo 获取 PagefileUsage
Windows 没有“虚拟内存大小”的单一定义,开发者常混淆 WorkingSetSize(物理内存占用)、PagefileUsage(提交内存,即已保留+已提交的虚拟地址空间总量)和 PeakPagefileUsage(历史峰值)。真正对应 Linux VmSize 的是 PROCESS_MEMORY_COUNTERS::PagefileUsage。
容易踩的坑:
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
- 必须链接
psapi.lib,且在 VS 中需定义PSAPI_VERSION=1(否则默认用 v2,部分老系统不支持) -
GetProcessMemoryInfo(GetCurrentProcess(), &pmc, sizeof(pmc))返回 false 时,不能忽略错误码——常见原因是目标进程开启了低完整性级别(如 Edge 浏览器渲染进程),此时需用OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, ...)替代 -
PagefileUsage单位是字节,无需换算,但要注意它是“已提交”内存,不含仅保留(reserved)未提交(committed)的地址空间(这类空间不计入该值,但属于进程虚拟地址空间的一部分)
C++ 跨平台封装时别碰 mallinfo 和 malloc_stats
这两个 glibc 接口看起来能反映堆内存,但它们和“进程虚拟内存大小”完全不是一回事:mallinfo 只统计 malloc 分配器管理的堆块(不含 mmap 分配的独立段、不包含代码段/数据段/共享库),malloc_stats 更只是打印到 stderr 的调试信息,无法安全解析。
实际项目中见过有人用 mallinfo().usmblks 当虚拟内存用,结果在启用了 M_MMAP_THRESHOLD 的服务进程中数值骤降——因为大对象改走 mmap,不再进 malloc heap 统计范围。
所以:
- 跨平台封装时,Linux 走
/proc/self/statm,Windows 走GetProcessMemoryInfo,两者逻辑分离,不要试图抽象成一个“get_vmsize()”统一接口 - 若需粗略估算(例如日志告警阈值),可用
sbrk(0)差值 +brk()历史调用次数反推,但这极其不可靠,仅限调试
注意 mmap 匿名映射和共享内存的影响
虚拟内存大小包含所有映射区域:代码段、数据段、堆、栈、动态库、mmap 映射(含 MAP_ANONYMOUS)、POSIX 共享内存(shm_open)、甚至 /dev/mem 这类设备映射。这些在 /proc/self/statm 和 PagefileUsage 中都会被计入。
这意味着:
- 如果程序大量使用
mmap(nullptr, size, ..., MAP_PRIVATE | MAP_ANONYMOUS),虚拟内存会快速上涨,但 RSS 几乎不增——这是正常行为,不代表泄漏 - 调用
shm_unlink后,共享内存段仍被计入虚拟内存,直到所有进程都munmap它;ipcs -m显示 “dest” 状态时,statm里还留着,这点容易误判 - 在容器中(如 Docker),
/proc/self/statm返回的是宿主机视角的虚拟地址空间,不受--memory限制影响——cgroup 限制的是物理内存(RSS)和 swap 使用,不是虚拟地址空间上限
/proc/PID/maps 比盯 mallinfo 有用得多。C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










