VirtualAlloc/Ex分配的是何种内存?是否属于C/C++程序的堆内存?
VirtualAlloc 到底从哪分配内存?
嘿,这个问题抓得很准!你说得完全没错——VirtualAlloc 确实不是从你用 HeapAlloc 的那个常规用户堆里分配内存的,它属于Windows内存模型里更底层、更灵活的一块区域。下面给你掰明白这事儿:
先搞懂Windows进程的地址空间布局
Windows进程的用户态地址空间(32位下是2GB/4GB,64位下则大得多)大致分成这几个部分:
.text、.data、.rodata这些可执行镜像段:程序加载时就固定下来的,存放代码、全局变量、常量;- 栈:每个线程专属,自动分配释放,存放局部变量、函数调用上下文;
- 堆:包括系统默认堆和你用
HeapCreate创建的私有堆,是封装好的“内存池”,用来分配小块、频繁使用的内存(malloc、new底层其实也是堆操作); - 空闲虚拟地址空间:这就是
VirtualAlloc的主战场!
VirtualAlloc 的本质:直接操作虚拟内存页
VirtualAlloc 是直接和Windows虚拟内存管理器(VMM)交互的API,它做的是:
- 首先预留一段连续的虚拟地址范围(这时候还没占用物理内存);
- 你可以选择立即提交物理内存到这些虚拟页,或者后续用到时再提交;
- 还能直接设置内存的保护属性(比如
PAGE_EXECUTE_READWRITE用来存放动态生成的机器码,这是堆做不到的)。
和 HeapAlloc 的核心区别
HeapAlloc是从一个已经通过VirtualAlloc(系统默认堆就是系统预先用VirtualAlloc建好的)预留/提交的堆区域里,切割出小块内存给你用——相当于“从现成的池子里舀水”;VirtualAlloc是直接向系统申请一块全新的、独立的虚拟地址区域——相当于“自己挖一个新池子”。
什么时候该用 VirtualAlloc?
一般推荐用它的场景:
- 需要分配大块内存(比如几MB甚至几十MB以上),用堆的话容易产生碎片;
- 需要自定义内存保护属性(比如要执行动态生成的代码,或者要创建只读的大内存块);
- 需要精确控制内存的提交/释放时机(比如先预留地址,用到的时候再提交物理内存,节省资源)。
最后提醒一句:VirtualAlloc 分配的内存必须用 VirtualFree 释放,绝对不能和堆的API混用(比如用 HeapFree 去释放虚拟内存,肯定会炸)!
内容的提问来源于stack exchange,提问作者user9782286
相关产品推荐
相关产品推荐

