You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

GlobalMemoryStatusEx未统计动态分配数组内存占用的问题

问题解析:Windows虚拟内存机制导致的内存统计差异

这个问题的核心在于Windows的虚拟内存管理逻辑——具体是延迟物理内存分配和**写时复制(Copy-On-Write)**的特性,我来给你一步步拆解:

1. std::vector::resize为什么会被统计到?

当你调用v.resize(1000000000)时,vector做了两件关键的事:

  • 首先向系统申请了10亿个int64_t对应的虚拟地址空间;
  • 然后默认初始化所有元素(int64_t的默认值是0),也就是对每一个元素执行写操作。

这第二步是核心:每个写操作都会触发Windows的写时复制机制,迫使系统为对应的内存页面分配实际的物理内存。10亿个int64_t总共是8GB左右的内存,这部分物理内存被真实分配,自然会被GlobalMemoryStatusEx的ullAvailPhys字段统计到,所以你看到Mem0和Mem1的差值接近8GB。

2. new/malloc为什么没被统计?

而new int64_t[1000000000]或者malloc的行为完全不同:

  • 它们只会向系统预留虚拟地址空间,但不会立即分配任何物理内存。Windows采用延迟物理内存分配策略,只有当你真正对某块内存执行写操作时,系统才会为对应的内存页面分配物理内存。
  • 你尝试的v[1000000000-1]=0只修改了最后一个元素,也就是只触发了一个内存页面的物理分配(Windows默认页面大小是4KB,一个页面能容纳512个int64_t)。这点内存占用在16GB的总内存里几乎可以忽略,所以Mem0和Mem1的差值接近0。

3. 如何让new/malloc的内存被统计到?

如果你想让new/malloc分配的内存被GlobalMemoryStatusEx检测到,需要触发所有内存页面的写操作。比如用循环遍历所有元素并赋值:

Mem0=FreeMBs();
int64_t* v=new int64_t[1000000000];
// 遍历所有元素,强制分配物理内存
for(size_t i=0; i<1000000000; ++i){
    v[i] = 0;
}
Mem1=FreeMBs();

这时你会看到Mem0和Mem1的差值同样接近8GB,和vector的表现一致。

4. 补充:虚拟内存 vs 物理内存的区别

Windows的虚拟内存系统会给进程分配大量的虚拟地址空间,但物理内存是稀缺资源。为了高效利用物理内存,系统只会在实际需要读写时才分配物理页。GlobalMemoryStatusEx的ullAvailPhys统计的是当前可用的物理内存,只有当物理内存被真实分配时,这个数值才会发生明显变化。


内容的提问来源于stack exchange,提问作者NoComprende

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 07:10:40