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
相关产品推荐
相关产品推荐

