globalmemorystatusex函数通过memorystatusex结构体的ullavailvirtual字段返回当前进程可用的虚拟地址空间剩余量,而非页面文件或物理内存大小;该值表示尚未被占用的用户态可寻址空间,32位进程默认最多2gb,64位进程可达数tb,调用前必须初始化dwlength为sizeof(memorystatusex)。

Windows 下用 GlobalMemoryStatusEx 获取可用虚拟内存
Windows 不区分“虚拟内存”和“页面文件”的概念,它把整个用户态可寻址空间(包括已提交、保留但未提交、以及尚未分配的部分)统称为“虚拟内存”。真正能用于新 VirtualAlloc 分配的,是 ullAvailVirtual 字段——即当前进程可用的虚拟地址空间剩余量。
注意:这不是物理内存或页面文件大小,而是 32 位进程最多 2GB(默认)或 3GB(/LARGEADDRESSAWARE),64 位进程理论上可达数 TB 的地址空间中,尚未被占用的部分。
-
GlobalMemoryStatusEx必须传入已初始化的MEMORYSTATUSEX结构体,且dwLength = sizeof(MEMORYSTATUSEX),否则返回失败 - 调用后检查返回值,失败时用
GetLastError()排查(常见是结构体没设dwLength) -
ullAvailVirtual是ULONGLONG类型,别用%d打印,要用%I64u或std::to_string
MEMORYSTATUSEX memInfo;
memInfo.dwLength = sizeof(memInfo);
if (GlobalMemoryStatusEx(&memInfo)) {
std::cout
<h3>Linux 下没有直接等价 API,需解析 <code>/proc/self/status</code>
</h3>
<p>Linux 内核不提供单个系统调用返回“当前可用虚拟内存”,因为虚拟地址空间管理更细粒度(按 vma 区间),且受 <code>vm.max_map_area</code>、<code>RLIMIT_AS</code> 等多层限制。最接近的指标是 <code>VmPeak</code> 和 <code>VmSize</code> 的差值趋势,但真正决定能否继续 <code>mmap</code> 的是进程的 <code>RLIMIT_AS</code>(address space limit)和内核剩余可映射区域。</p><div class="aritcle_card flexRow artxards">
<div class="artcardd flexRow">
<a class="aritcle_card_img" rel="nofollow" href="/xiazai/gongju/2823" title="C++14"><img
src="https://img.php.cn/upload/manual/001/431/639/6ac8b33c327c4749.png" alt="C++14" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a>
<div class="aritcle_card_info flexColumn">
<a rel="nofollow" href="/xiazai/gongju/2823" title="C++14" class="overflowclass">C++14</a>
<p class="overflowclass">C++14 对 C++11 的修正与增强版本,适合旧系统维护和较老工具链兼容。</p>
</div>
<a rel="nofollow" href="/xiazai/gongju/2823" title="C++14" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span>
</a>
</div>
</div>
- 读取
/proc/self/status中的VMPeak:和VMSize:行,单位 KB;二者差值反映“历史峰值与当前使用量之差”,不是剩余容量 - 更实用的是检查资源限制:
getrlimit(RLIMIT_AS, &rlim),rlim.rlim_cur是软限制(bytes),超限时mmap返回ENOMEM - 不要依赖
/proc/meminfo里的CommitLimit或Committed_AS,那是系统级内存承诺估算,不对应单个进程的虚拟地址空间余量
跨平台封装要注意:虚拟内存 ≠ 物理内存,也 ≠ 页面文件大小
很多开发者误以为“可用虚拟内存”就是“空闲页面文件大小”,这是典型混淆。Windows 的 ullAvailPageFile 是页面文件剩余量,Linux 的 SwapFree 是交换区空闲量——它们影响的是内存换出能力,而非进程还能否成功 malloc 或 mmap。
- 对 32 位程序,
ullAvailVirtual可能只剩几十 MB,即使物理内存充足,也会因地址空间耗尽而malloc失败 - 64 位程序通常不会遇到虚拟地址空间不足,除非大量使用
mmap(MAP_FIXED)或泄漏 vma 区间 - 如果目标是预判 OOM 风险,应同时监控:
RLIMIT_AS(Linux)、ullAvailVirtual(Windows)、以及实际malloc是否返回nullptr
容易忽略的关键点:32 位 vs 64 位、/LARGEADDRESSAWARE、ASLR
同一个 Windows 程序,在 32 位下默认只有 2GB 用户空间;加了 /LARGEADDRESSAWARE 并运行在 64 位系统上,才能拿到 3GB(或 4GB 启用 /3GB)。而 ASLR(地址空间布局随机化)会让每次启动的基址偏移不同,导致 ullAvailVirtual 数值波动——这不是错误,是正常行为。
- Visual Studio 链接时加
/LARGEADDRESSAWARE,否则即使编译为 x64,32 位进程也无法突破 2GB - Linux 上启用
CONFIG_CHECKPOINT_RESTORE或使用userfaultfd会额外消耗 vma,但不影响RLIMIT_AS计算 - 不要在循环里高频调用
GlobalMemoryStatusEx或反复打开/proc/self/status,开销小但无必要
真正需要关心虚拟内存余量的场景其实很窄:长时间运行的嵌入式服务、自定义内存池管理器、或调试地址空间泄漏。多数应用只需关注 malloc 失败并处理异常即可。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










