【问题标题】:VirtualAlloc MEM_COMMIT and MEM_RESERVEVirtualAlloc MEM_COMMIT 和 MEM_RESERVE
【发布时间】:2014-11-19 16:23:35
【问题描述】:

我对 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;
}

没有错误

【问题讨论】:

  • 因为第一个在技术上是不正确的。没有保留就不能提交。
  • 但是我可以使用下面的函数来分配缓冲区,如下所示: void* pdata = VirtualAlloc(NULL, 64*1024*1024, MEM_COMMIT, PAGE_READWRITE); if (pdata == NULL) { cout
  • 操作系统可以猜出你的意思。所以没有区别。
  • 但是你应该通过这两个。不要让操作系统掩盖你的错误。总有一天,操作系统可能不再那么适应编程错误。
  • 我明白了,谢谢你的帮助。原来操作系统是个好人

标签: memory virtualalloc


【解决方案1】:

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

操作系统会计算保留你的块的位置。 但它不会分配任何东西。 (要了解操作系统是如何做到这一点的,只需查看诸如 Mark Russinovich 的“Windows Internals 5th”之类的书籍——提示:在 Google 上搜索 VAD 树)。

因此,当您保留一块内存时,操作系统将简单地在某处的树或类似结构上分配一个“节点”,表示这些地址已保留,就像餐厅的桌子一样,并且不能用于对VirtualAlloc() 的其他调用。

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

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

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

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

【讨论】:

  • 如果我只需要小于或等于页面大小的连续分配,可以单独调用 MEM_COMMIT 吗?
  • 好吧,假设使用VirtualAlloc(),您正在分配的内存。如果您尝试分配 VirtualAlloc() 时,您应该始终考虑页面,至少我是这样做的。同样的事情也适用于 Unix 中的 mmap()
猜你喜欢
  • 1970-01-01
  • 2015-10-18
  • 1970-01-01
  • 2021-03-16
  • 2015-10-13
  • 2011-12-04
  • 2020-05-28
  • 2015-07-04
相关资源
最近更新 更多