必须初始化memStat.dwLength = sizeof(MEMORYSTATUSEX),否则GlobalMemoryStatusEx返回FALSE;已用内存=ullTotalPhys−ullAvailPhys,空闲内存=ullAvailPhys;32位程序需启用/LARGEADDRESSAWARE才能正确获取超4GB内存值。

GlobalMemoryStatusEx 返回值为 FALSE 怎么办
调用 GlobalMemoryStatusEx 前必须初始化 MEMORYSTATUSEX 结构体的 dwLength 成员,否则 Windows 直接返回 FALSE 且不填充数据。这是最常见也最容易忽略的错误。
- 必须写:
memStat.dwLength = sizeof(MEMORYSTATUSEX); - 结构体变量建议栈上分配(无需
new),避免未初始化内存残留 - 调用后检查返回值:
if (!GlobalMemoryStatusEx(&memStat)) { /* GetLastError() 可查具体失败原因 */ }
如何正确计算已用内存和空闲内存(单位:字节)
GlobalMemoryStatusEx 不直接提供“已用”字段,需手动推导。关键字段是 ullTotalPhys(总物理内存)和 ullAvailPhys(当前可用物理内存),两者相减才是当前已用物理内存。
- 空闲内存 =
memStat.ullAvailPhys - 已用内存 =
memStat.ullTotalPhys - memStat.ullAvailPhys - 注意:不要用
ullAvailPageFile或ullAvailVirtual替代——它们反映的是页面文件或虚拟地址空间余量,不是物理内存使用状态
为什么在 32 位程序里 ullTotalPhys 显示不准
即使你编译的是 32 位 C++ 程序,只要操作系统是 64 位且物理内存超过 4GB,ullTotalPhys 仍能正确返回真实值(如 17179869184 表示 16GB)。但前提是你的进程启用了 /LARGEADDRESSAWARE 链接选项;否则 Windows 会限制其可见内存上限为 2GB(或 3GB),导致 GlobalMemoryStatusEx 内部可能截断或误报。
- Visual Studio 中启用方法:项目属性 → 链接器 → 系统 → 启用大地址感知 → 是(
/LARGEADDRESSAWARE) - 命令行链接时加:
link /LARGEADDRESSAWARE - 用
dumpbin /headers your.exe | findstr "large"可验证是否生效
要不要用 GetPhysicallyInstalledSystemMemory 替代
GetPhysicallyInstalledSystemMemory 返回的是 BIOS 报告的**物理安装容量**(即插了多少条内存条),不是当前系统可用或已用状态。它不随内存分配/释放变化,也无法反映页面交换、驱动保留内存等运行时因素。
立即学习“C++免费学习笔记(深入)”;
- 适合做硬件信息展示,不适合做内存监控
- 它不依赖
MEMORYSTATUSEX初始化,调用更简单,但用途完全不同 - 真实监控场景下,必须用
GlobalMemoryStatusEx,并持续轮询(注意别太频繁,1–2 秒一次足够)
实际监测中容易漏掉的是:驱动程序、GPU 显存预留、Hyper-V 等虚拟化组件会占用一部分物理内存,这部分既不计入进程私有工作集,也不会体现在 ullAvailPhys 的“减少量”里——它从开机起就已被划走,GlobalMemoryStatusEx 返回的是剩余可调度部分,已经扣除了这些。










