linux 用 /proc/self/status 读 vmrss 字段得 rss(kb),windows 调 getprocessmemoryinfo 取 workingsetsize;二者最贴近真实物理内存占用,跨平台应优先选用,避免 mallinfo 等不完整方案。

Linux 下用 /proc/self/status 读取实时 RSS 内存值
Linux 进程的内存占用(主要是物理内存,即 RSS)能直接从 /proc/self/status 里拿到,不需要外部工具或侵入式 hook。这是最轻量、最可靠的一键检测方式。
关键字段是 rss(单位为 pages),需乘以 getpagesize() 才是字节数;rss_anon 和 rss_file 可选,用于区分堆/匿名映射 vs 文件映射内存。
- 必须用
fopen("/proc/self/status", "r"),不能用stat()或readlink()—— 后者不反映当前 RSS - 解析时建议逐行
fgets()+sscanf(),匹配"VmRSS:"行更稳定(比Rss:兼容老内核) - 注意:该值是采样快照,非原子更新;高频率读取(如每毫秒)会显著拖慢程序,建议间隔 ≥100ms
long get_rss_kb() {
FILE* f = fopen("/proc/self/status", "r");
if (!f) return 0;
char line[256];
long rss = 0;
while (fgets(line, sizeof(line), f)) {
if (sscanf(line, "VmRSS: %ld kB", &rss) == 1) break;
}
fclose(f);
return rss;
}
Windows 上调用 GetProcessMemoryInfo 获取工作集大小
Windows 没有 /proc,等效的是 GetProcessMemoryInfo,返回的 WorkingSetSize 字段最接近 Linux 的 RSS —— 即当前被锁定在物理内存中的页数。
它不包含已换出或共享的页,也不含 pagefile 预留空间,所以比 PrivateUsage 更贴近“真实占了多少 RAM”。
立即学习“C++免费学习笔记(深入)”;
- 必须链接
psapi.lib,且运行时需加载psapi.dll(Win7+ 原生支持) - 传入的
HANDLE必须有PROCESS_QUERY_INFORMATION权限,用GetCurrentProcess()最安全 - 返回值是字节,但精度受系统页大小影响(通常 4KB),小变化可能被抹平
#include <psapi.h>
size_t get_working_set_bytes() {
PROCESS_MEMORY_COUNTERS pmc;
if (GetProcessMemoryInfo(GetCurrentProcess(), &pmc, sizeof(pmc))) {
return pmc.WorkingSetSize;
}
return 0;
}
跨平台封装时别碰 mallinfo 和 malloc_stats
mallinfo 看似方便,但它只统计 glibc malloc 管理的堆内存,漏掉 mmap 分配的大块内存(比如大 vector、shared_ptr 缓冲区)、静态数据段、线程栈,结果严重偏低。
malloc_stats 是打印到 stderr 的文本,无法直接提取数值,且输出格式无保证(glibc 版本一变就崩)。
- 即使你只用 new/delete,C++ 运行时也可能底层调用
mmap(尤其 >128KB 时),mallinfo完全看不见 - ASan/TSan 等 sanitizer 会彻底禁用
mallinfo,调用直接返回 0 - 真正跨平台的底线做法:Linux 走
/proc/self/status,Windows 走GetProcessMemoryInfo,其他系统(macOS)用task_info+MACH_TASK_BASIC_INFO
高频监控时 RSS 值跳变大?先关掉 THP 和检查 madvise
Linux 下 RSS 突然暴涨几十 MB 又回落,大概率不是内存泄漏,而是透明大页(THP)触发了页表重组,或程序调用了 madvise(..., MADV_DONTNEED) 导致内核延迟回收页框。
这类波动不影响功能,但会让监控曲线毛刺严重,误报 OOM 风险。
- 临时关闭 THP:
echo never > /sys/kernel/mm/transparent_hugepage/enabled - 检查代码是否在
free()前调了madvise(addr, len, MADV_DONTNEED)—— 这会让 RSS 瞬间归零,但物理页未必立即释放 - 若需稳定 baseline,建议在空闲循环中连续采样 3 次取中位数,而非单次读取
物理内存统计从来不是精确科学,RSS 只是快照,而内核调度、页回收、缓存策略都在后台持续搅动。盯住趋势,别信单点值。








