windows下最直接兼容的方式是调用globalmemorystatusex获取memorystatusex结构体,通过(ulltotalphys - ullavailphys) / ulltotalphys * 100.0计算物理内存使用率,需正确初始化dwlength、避免整数溢出并检查返回值。

用 GlobalMemoryStatusEx 获取总物理内存使用率
Windows 下最直接、兼容性最好的方式是调用 GlobalMemoryStatusEx,它返回 MEMORYSTATUSEX 结构体,其中 ullTotalPhys 和 ullAvailPhys 分别表示总物理内存和当前可用物理内存(单位字节)。利用率 = (ullTotalPhys - ullAvailPhys) / ullTotalPhys * 100.0。
注意:该函数从 Windows XP SP2 开始支持,现代系统(Win7+)全部可用;不要用已废弃的 GlobalMemoryStatus(精度低、不支持 >4GB 内存)。
-
GlobalMemoryStatusEx必须传入已初始化dwLength字段的MEMORYSTATUSEX实例,否则返回失败 - 计算时务必用
double或uint64_t避免整数溢出——ullTotalPhys可能超 4GB,直接用int除会截断 - 返回值为
BOOL,需检查是否为TRUE,失败时GetLastError()可能返回ERROR_INVALID_PARAMETER
代码示例:安全获取并计算内存使用率
以下是最小可行实现,含错误检查和类型转换:
double getPhysicalMemoryUsagePercent() {
MEMORYSTATUSEX memInfo;
memInfo.dwLength = sizeof(MEMORYSTATUSEX);
if (!GlobalMemoryStatusEx(&memInfo)) {
return -1.0; // 调用失败
}
if (memInfo.ullTotalPhys == 0) return 0.0;
double used = static_cast<double>(memInfo.ullTotalPhys - memInfo.ullAvailPhys);
return (used / memInfo.ullTotalPhys) * 100.0;
}</double>
调用后可四舍五入到小数点后一位:std::round(usage * 10.0) / 10.0。注意 ullAvailPhys 包含 standby list 中的内存,Windows 认为其“可用”,所以这个值反映的是内核视角的实时压力,不是任务管理器里“已提交”那种统计口径。
为什么不用 WMI 或 Performance Counters?
WMI(如 Win32_OperatingSystem.TotalVisibleMemorySize)和性能计数器(\Memory\% Committed Bytes In Use)也能拿到类似数据,但它们有明显短板:
- WMI 启动慢、依赖 COM 初始化、容易因权限或服务状态失败,不适合高频或启动阶段调用
- 性能计数器返回的是“提交内存占比”,受页面文件大小影响,和物理内存实际占用无直接关系
- 两者都需要额外链接库(
ole32.lib、pdh.lib)和更复杂的错误处理,而GlobalMemoryStatusEx只需kernel32.lib
除非你在写监控服务且需要历史趋势或跨机器聚合,否则没必要绕路。
常见错误现象与排查点
实际使用中遇到返回 0 或负值,大概率是这几个原因:
-
memInfo.dwLength没设成sizeof(MEMORYSTATUSEX)→ 返回FALSE,ullTotalPhys保持未初始化垃圾值 - 在 32 位程序中用
unsigned long接收ullTotalPhys→ 高 32 位丢失,导致总数远小于实际,算出虚高利用率 - 没检查
ullTotalPhys == 0就直接除 → 触发浮点异常(若开启 FPE 捕获)或返回inf/nan - 误把
ullAvailPageFile当作物理内存可用量 → 它是页面文件剩余空间,和物理内存无关
真正难处理的其实是“瞬时抖动”:比如某个后台进程瞬间申请 2GB 内存又释放,GlobalMemoryStatusEx 会如实反映这一帧的峰值,但用户感知不到。如果要做平滑显示,得自己加滑动窗口或低通滤波,API 本身不提供这类能力。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











