GetProcessMemoryInfo返回的WorkingSetSize与任务管理器不一致,因前者含共享页而后者显示Private Working Set(独占物理内存),需用PROCESS_MEMORY_COUNTERS_EX结构并正确初始化cb字段才能获取PrivateUsage对齐任务管理器。

GetProcessMemoryInfo 为什么返回的 WorkingSetSize 和实际任务管理器不一致
因为 GetProcessMemoryInfo 返回的 WorkingSetSize 是当前进程工作集大小(即驻留物理内存页数),而任务管理器“内存使用量”默认显示的是 Private Working Set —— 排除了共享页、映射文件页等非独占内存。两者统计口径不同,差几百 MB 很常见。
真正反映“该进程独占用了多少物理内存”的字段是 PrivateUsage,但它不在 PROCESS_MEMORY_COUNTERS 结构里,得用扩展结构 PROCESS_MEMORY_COUNTERS_EX 并调用带 _EX 后缀的函数。
- 必须用
GetProcessMemoryInfo(旧版)或GetProcessMemoryInfoEx(不存在!注意:Windows API 实际只有GetProcessMemoryInfo,但需传入PROCESS_MEMORY_COUNTERS_EX结构才能拿到PrivateUsage) -
PROCESS_MEMORY_COUNTERS_EX的cb字段必须初始化为sizeof(PROCESS_MEMORY_COUNTERS_EX),否则 API 直接失败返回 0 - 需要
#include <psapi.h>且链接psapi.lib(或运行时 LoadLibrary + GetProcAddress 兜底)
如何正确调用 GetProcessMemoryInfo 获取 PrivateUsage
核心是结构体类型和初始化顺序不能错。下面这段代码能稳定拿到当前进程的私有物理内存占用(单位字节):
PROCESS_MEMORY_COUNTERS_EX pmc = {0};
pmc.cb = sizeof(pmc);
if (GetProcessMemoryInfo(GetCurrentProcess(), (PPROCESS_MEMORY_COUNTERS)&pmc, sizeof(pmc))) {
SIZE_T private_kb = pmc.PrivateUsage / 1024;
printf("Private physical memory: %zu KB\n", private_kb);
}
注意:GetProcessMemoryInfo 第二个参数类型是 PPROCESS_MEMORY_COUNTERS,但传 &pmc 是安全的——因为 PROCESS_MEMORY_COUNTERS_EX 前半部分与 PROCESS_MEMORY_COUNTERS 完全兼容。Windows 就靠这个 cb 字段判断你传的是哪种结构。
立即学习“C++免费学习笔记(深入)”;
- 如果只定义
PROCESS_MEMORY_COUNTERS,就永远拿不到PrivateUsage - 忘记设
pmc.cb→ 函数返回 FALSE,GetLastError()是 87(ERROR_INVALID_PARAMETER) - 在 Windows 7+ 才支持
PrivateUsage;XP 下该字段恒为 0
WorkingSetSize、PagefileUsage、PrivateUsage 三个值怎么选
看你要回答什么问题:
- “此刻有多少物理内存被这个进程锁着没被换出?” → 看
WorkingSetSize(但含共享页) - “它实际占用了多少独占物理内存?” → 看
PrivateUsage(最贴近用户感知的“内存占用”) - “它总共申请了多少虚拟内存,含已换出到页面文件的部分?” → 看
PagefileUsage(和PrivateUsage接近,但含已换出页)
PrivateUsage 是三者中唯一能和任务管理器“私有工作集”列对齐的指标,也是诊断内存泄漏最可靠的物理内存维度。
权限不足或跨 32/64 位导致 GetProcessMemoryInfo 失败
调用失败不一定是代码写错了,很可能是权限或架构问题:
- 目标进程开启了
SeDebugPrivilege权限才允许读取其内存信息;普通进程查自己没问题,查别人可能失败(错误码 5:ACCESS_DENIED) - 32 位程序调用
GetProcessMemoryInfo查 64 位进程会失败(错误码 299:ERROR_PARTIAL_COPY),反之亦然 - UAC 提权后仍失败?检查是否以“管理员身份运行”,而非仅声明了
requireAdministrator清单
查自己进程时,上述问题基本不会触发;但封装成通用工具时,必须预判这些边界条件,否则在客户机器上静默失败。
PrivateUsage 字段容易被忽略,但它才是物理内存占用的真实度量——尤其当进程大量使用 DLL 或内存映射文件时,WorkingSetSize 会严重高估实际压力。


















