Windows下必须用GlobalMemoryStatusEx获取内存信息,因其支持超4GB内存且ullTotalPhys和ullAvailPhys字段分别准确返回总物理内存和可用物理内存字节数,调用前须初始化dwLength成员并链接kernel32.lib。

Windows 下用 GlobalMemoryStatusEx 获取内存信息
Windows 不提供 POSIX 接口,必须调用 WinAPI。直接用 GlobalMemoryStatusEx 是最稳妥的方式,它支持大于 4GB 的内存(GlobalMemoryStatus 已废弃)。结构体 MEMORYSTATUSEX 的 ullTotalPhys 字段即总物理内存字节数,ullAvailPhys 是当前可用物理内存。
注意:必须初始化 dwLength 成员,否则调用失败返回 false;且需链接 kernel32.lib(MSVC 默认链接,MinGW 需显式加 -lkernel32)。
- 示例关键代码:
MEMORYSTATUSEX memInfo; memInfo.dwLength = sizeof(MEMORYSTATUSEX); GlobalMemoryStatusEx(&memInfo); uint64_t totalMB = memInfo.ullTotalPhys / (1024 * 1024);
- 错误现象:
GlobalMemoryStatusEx返回false→ 多数因未设dwLength -
ullTotalPhys是 uint64_t,别用DWORD或unsigned long接收,否则在 64GB+ 系统上溢出
Linux/macOS 下读取 /proc/meminfo 或 sysctl
Linux 通过解析 /proc/meminfo 最可靠,字段如 MemTotal: 和 MemAvailable:(非 MemFree:,后者不含可回收缓存)。macOS 没有 /proc,得用 sysctl 查询 hw.memsize(总内存)和 vm.stats.vm.v_free_count(需换算)。
差异点:Linux 的 MemAvailable 是内核 3.14+ 引入的估算值,比 MemFree + Buffers + Cached 更准;macOS 的空闲内存计算更复杂,通常建议只取总内存,运行时可用内存推荐用 host_statistics API(需 Mach 权限)。
立即学习“C++免费学习笔记(深入)”;
- Linux 示例(简单解析):
std::ifstream f("/proc/meminfo"); std::string line; while (std::getline(f, line)) { if (line.rfind("MemTotal:", 0) == 0) { sscanf(line.c_str(), "MemTotal: %lld kB", &totalKB); break; } } - macOS 总内存:
sysctl -n hw.memsize返回字节数;但vm.stats.vm.v_free_count单位是页(page size),需乘getpagesize() - 避免直接依赖
MemFree:它常接近 0,不代表系统卡顿;MemAvailable才反映真实可分配量
跨平台封装时绕不开的陷阱
没有标准 C++ 接口,硬写跨平台函数必须条件编译。常见翻车点不是逻辑错,而是单位混淆、符号类型误用、或忽略 macOS 权限限制。
- 统一用
uint64_t存储字节数,避免size_t在 32 位编译下截断(即使目标平台是 64 位,构建配置可能选了 ILP32) - Linux 上
/proc/meminfo字段名大小写敏感,且末尾有冒号和空格,正则或rfind比==安全 - macOS 的
host_statistics需要HOST_VM_INFOflavor,且返回的vm_page_t数量要乘vm_page_size,这个值不等于getpagesize()(Mach page size 可能不同) - 不要尝试用
std::system("free -b")解析输出:格式随 locale 和版本变,free命令本身不保证 ABI 稳定
为什么不用 GetPhysicallyInstalledSystemMemory?
这个 WinAPI 函数返回的是“物理安装容量”,不是当前操作系统可见的总内存(比如 BIOS 保留、UEFI frame buffer 占用、热插拔未启用等会导致二者不等)。实际开发中,程序关心的是 OS 能调度的内存上限,不是主板插了几条 DDR5。
-
GetPhysicallyInstalledSystemMemory返回值单位是 KB,但它是ULONGLONG,仍需注意类型匹配 - 它不反映内存热插拔、NUMA 节点隔离、或内核启动参数如
mem=的限制 - 多数监控、资源调度类逻辑应以
GlobalMemoryStatusEx的ullTotalPhys为准,而非硬件标称值
实际项目里,总内存数字本身很少单独用;真正容易出问题的是“当前可用”判断——Linux 的 MemAvailable 和 Windows 的 ullAvailPhys 含义接近但实现逻辑不同,拿同一套阈值去告警,很可能在 macOS 上完全失效。


















