windows下用globalmemorystatusex获取总物理内存最可靠,需初始化memorystatusex结构体的dwlength成员并检查返回值,ulltotalphys字段即为总字节数;linux则解析/proc/meminfo中memtotal行。

Windows下用GlobalMemoryStatusEx获取总物理内存
GlobalMemoryStatusEx 是 Windows 平台最可靠的方式,它返回 MEMORYSTATUSEX 结构体,其中 ullTotalPhys 字段就是总物理内存字节数。注意必须初始化结构体的 dwLength 成员,否则调用失败且不报错。
- 必须包含头文件:
#include <windows.h></windows.h> - 声明结构体时要先设
memStat.dwLength = sizeof(MEMORYSTATUSEX); - 返回值为
BOOL,需检查是否为TRUE,失败时GetLastError()可能返回ERROR_INVALID_PARAMETER -
ullTotalPhys是ULARGE_INTEGER类型,直接用.QuadPart成员读取 64 位整数值
MEMORYSTATUSEX memStat = {0};
memStat.dwLength = sizeof(MEMORYSTATUSEX);
if (GlobalMemoryStatusEx(&memStat)) {
uint64_t totalBytes = memStat.ullTotalPhys;
}
Linux下读取/proc/meminfo中的MemTotal
Linux 没有统一 API,标准做法是解析 /proc/meminfo 文件。关键字段是 MemTotal: 行,单位是 kB,需乘以 1024 转为字节。
- 不要用
sysconf(_SC_PHYS_PAGES)—— 它返回页数,但页大小可能非 4KB(如大页),且不反映实际物理容量 -
fopen("/proc/meminfo", "r")后逐行fgets,匹配以"MemTotal:"开头的行 - 注意空格和制表符,建议用
sscanf(line, "MemTotal: %lld kB", &kb)提取数值 - 若文件不可读(如容器中被挂载隔离),会返回 0 或失败,需做容错
FILE* f = fopen("/proc/meminfo", "r");
if (f) {
char line[256];
while (fgets(line, sizeof(line), f)) {
long long kb;
if (sscanf(line, "MemTotal: %lld kB", &kb) == 1) {
uint64_t totalBytes = kb * 1024ULL;
break;
}
}
fclose(f);
}
跨平台封装要注意的兼容性陷阱
想写一次代码跑两边?别直接宏定义分支,容易漏掉类型和头文件差异。
- Windows 需链接
kernel32.lib(通常默认链接),Linux 不需要额外库 -
uint64_t在 Windows 下需#include <stdint.h></stdint.h>或<cstdint></cstdint>,Linux 同样要求 -
ULARGE_INTEGER是 Windows 特有,Linux 下完全不用;反之/proc/meminfo在 Windows 上不存在 - 不要尝试用
std::filesystem判断路径是否存在来“探测系统”——C++17 之前不可靠,且增加依赖
为什么GetPhysicallyInstalledSystemMemory不推荐
Windows 还有个 GetPhysicallyInstalledSystemMemory,但它返回的是“已安装”的内存容量,不是“当前可用的物理内存”。两者在以下情况不一致:
- BIOS 设置了内存映射限制(如启用 Trusted Computing)
- 系统启用了 memory-mapped I/O 占用地址空间
- 多节点 NUMA 系统中部分内存被标记为 reserved
- Hyper-V 或其他虚拟化层截留了物理内存
GlobalMemoryStatusEx 的 ullTotalPhys 才是内核实际识别并可管理的物理内存总量,更符合“系统总物理内存”的语义。
实际开发中,如果用户明确要“插在主板上的内存条总大小”,才考虑 GetPhysicallyInstalledSystemMemory;绝大多数监控、资源估算场景,应优先用 GlobalMemoryStatusEx。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











