Linux用sysinfo()获取总内存需将totalram乘以getpagesize()转字节;Windows推荐GetPhysicallyInstalledSystemMemory(SMBIOS值);macOS需host_statistics64+HOST_VM_INFO64组合计算,三者单位不同,统一用uint64_t避免溢出。

Linux 下用 sysinfo 获取总内存最可靠
直接读 /proc/meminfo 虽然简单,但解析易出错;sysinfo() 是内核提供的标准接口,返回的 totalram 字段单位是页(page),需乘以 getpagesize() 才是字节数。注意它返回的是物理内存总量,不含 swap。
常见错误:把 sysinfo 的 totalram 当成字节直接用,结果小了 4096 倍(默认页大小)。
- 必须检查
sysinfo()返回值是否为 0,失败时 errno 可能是ENOMEM -
getpagesize()在多数系统上是常量,但不能硬编码,尤其在嵌入式或非 x86 架构下 - 若需 MB 单位,建议用
(uint64_t)info.totalram * getpagesize() / (1024ULL * 1024),避免 int 溢出
Windows 用 GetPhysicallyInstalledSystemMemory 更准
GlobalMemoryStatusEx 返回的是“可用物理内存上限”,可能低于实际安装容量(比如被 BIOS 保留、PCIe 设备占用);而 GetPhysicallyInstalledSystemMemory 直接读取 SMBIOS,反映主板上插着的内存条总容量,单位是 KB。
这个函数从 Windows Vista 起可用,不支持 XP;调用前要确认函数指针是否非空,因为某些精简版系统可能未导出。
立即学习“C++免费学习笔记(深入)”;
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
- 返回值是
DWORD64,不是size_t,别用%zu格式化打印 - 若需字节单位,乘以 1024,不要用
1024ULL强制提升——参数本身已是 64 位 - 它不区分是否被系统保留,所以数值通常比
GlobalMemoryStatusEx的ullTotalPhys略大
macOS 需组合 host_statistics64 和 HOST_VM_INFO64
macOS 没有类似 sysinfo 的单一接口,得先用 host_port = mach_host_self() 获取 host port,再调用 host_statistics64() 并传入 HOST_VM_INFO64。其中 vm_statistics64_data_t::pagesize 是页大小,free_count + active_count + inactive_count + wired_count 才是总物理页数。
容易漏掉的是:必须链接 -framework CoreServices -framework IOKit,且头文件顺序敏感——#include <mach/mach.h> 必须在 <mach/host_info.h> 之前。
-
host_statistics64返回KERN_SUCCESS才算成功,否则字段值不可信 - 不要只用
wired_count + active_count,那只是“正在用”的部分,缺了inactive(可回收但未清空的页) - macOS Monterey 后部分 M1/M2 设备会报告 “unified memory”,此时该值仍代表 RAM 总量,不包含显存虚拟部分
C++ 跨平台封装要注意页大小和整型宽度
三个平台返回的原始单位不同:Linux 是页、Windows 是 KB、macOS 是页;统一转成字节后,uint64_t 是唯一安全选择——32 位 size_t 在 64GB+ 内存机器上会截断。
另一个坑是编译器对 sizeof(long) 的处理:Linux glibc 下 long 是 8 字节,Windows MSVC 下仍是 4 字节,所以别用 unsigned long 存总内存值。
- 跨平台代码里,
getpagesize()在 Windows 不可用,要用GetSystemInfo().dwPageSize - macOS 的
mach_port_t是指针类型,不能直接== NULL,得用MACH_PORT_NULL - 如果项目已用 CMake,记得在 macOS 上加
find_library(IOKIT_LIBRARY IOKit),否则链接失败没提示

















