memory - VirtualAlloc MEM_COMMIT 和 MEM_RESERVE

标签 memory virtualalloc

我对 VirtualAlloc 有点困惑,

我们可以使用 MEM_RESERVE 保留内存,然后使用 MEM_COMMIT 提交它,但我对以下两个函数使用时的区别有点困惑:

m_pvData = VirtualAlloc(NULL, m_nBuffSize, MEM_COMMIT, PAGE_READWRITE);
m_pvData = VirtualAlloc(NULL, m_nBuffSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);

第二个选择有什么好处?

我可以使用下面的函数来获取缓冲区:

void* pdata = VirtualAlloc(NULL, 64*1024*1024, MEM_COMMIT, PAGE_READWRITE);
if (pdata == NULL)
{
    cout<<"Last error is "<<GetLastError()<<endl;
}

没有错误

最佳答案

区别是这样的: 使用 MEM_RESERVE 你基本上是在对操作系统说:“嘿,拜托,我需要这个连续的虚拟内存页 block ,你能给我一个适合我需要的内存地址吗?”

操作系统会计算在哪里保留您的 block 。 但它还不会分配任何东西。 (要了解操作系统如何执行此操作,只需查看 Mark Russinovich 所著的《Windows Internals 5th》等书籍即可 - 提示:在 Google 上搜索有关 VAD 树的信息)。

所以,当你保留一 block 内存时,操作系统会简单地在某处的树上分配一个“节点”,或者类似的结构,说这些地址是保留的,就像餐厅的 table 一样,并且不能在对 VirtualAlloc() 的其他调用中使用。

相反,当您使用MEM_COMMIT实际提交页面时,操作系统实际上是在您之前保留的 block 上分配虚拟内存页面。 当然,您只能在之前保留的 block 上提交页面。 不这样做就像在餐厅预订座位,然后坐在另一张 table 上,而不是由您预订。

注意:这些页面实际上并没有分配,也没有提交,因为您对它们进行读/写(软页面错误)。这是一个非常有用的优化。

注意2:您可以 OR MEM_RESERVE|MEM_COMMIT 的事实只是有用的,因此您不必调用 `VirtualAlloc()' API 两次,但实际上它们仍然是两次非常不同的操作。

NOTE3:MEM_COMMIT 标志将在页面大小边界上提交页面,而使用 MEM_RESERVEMEM_RESERVE|MEM_COMMIT 将保留或保留+在大于页面大小的边界上提交页面,从今天起,在所有版本的 Windows 上通常为 64K。您可以通过调用 GetSystemInfo() 获取此号码。

关于memory - VirtualAlloc MEM_COMMIT 和 MEM_RESERVE,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57394359/

相关文章:

winapi - 如何限制进程的资源使用?

python - VirtualAlloc 和 Python - 访问冲突

c - 什么是 Linux/POSIX 等同于带有 MEM_TOP_DOWN 的 VirtualAlloc?

c# - 使用 VirtualAlloc 和 GetDelegateForFunctionPointer 在 C# 中运行字节数组时出错

c++ - 不能在 VirtualQuery 返回的空闲区域上使用 VirtualAlloc

c++ - VirtualAlloc 失败

windows - PE文件如何映射到内存中?

ios滚动过一个大的uiview内存问题

跨 2 个程序共享 C 内存

c# - 空指针使用多少内存?