【问题标题】:Free a Windows heap without releasing memory pages在不释放内存页的情况下释放 Windows 堆
【发布时间】:2014-08-16 17:10:50
【问题描述】:

我正在实现一个堆池实用程序,我需要一个 pool_clear() 函数(如 Apache Portable Runtime apr_pool_clear())。此函数允许我们立即释放(单个函数调用)该池上分配的所有内存,而无需将内存页面释放到底层系统。 Windows API 仅提供 HeapFree()(多个函数调用)和 HeapDestroy()(释放内存页面)。

有没有办法在 Windows 上做到这一点(使用原生 API)?

【问题讨论】:

  • “免费”是指“取消提交物理页面”,还是“标记为未被堆管理器使用但保持物理页面提交”? (注意,“释放”与这两者不同,它释放虚拟地址空间以及物理内存。)
  • @Mehrdad,OP 使用apr_pool_clear 作为类比,这让我相信他希望内存留在VirtualAlloc'd 但允许被堆重用。
  • 你不使用 VirtualAlloc 等吗?
  • 我使用 HeapCreate 创建堆,并将它与 HeapAlloc 和 HeapFree 一起使用。我要的是一种在不调用 HeapDestroy 的情况下一次性释放 HeapAlloc 分配的所有内存块的方法(我想重用该堆)。
  • 那是你的问题。你需要采取更多的控制。使用 VirtualAlloc 等。

标签: winapi heap-memory


【解决方案1】:

HeapCreate 和来自Kernel32 的其他Heap* 函数不提供这种功能。它们旨在提供与 C 标准库相同的功能,以及一些额外的调试/诊断功能。

听起来ntdll 中的RtlCreateHeap 符合要求,您自己分配内存并指定HeapBaseInitialCommitInitialReserveCommitRoutine

这意味着您可以调用 RtlDestroyHeap 而不会返回所有虚拟内存,然后使用相同的 HeapBase 再次调用 RtlCreateHeap,有效地在同一虚拟内存中创建一个新堆

不幸的是,据我所知,ntdll 中的这些入口点未记录as is most of the Native API,因此调用它存在风险。链接的文档是供驱动程序使用的Ntoskrnl 中的入口点。由于您使用 Native API 明确调用,也许您理解并接受这种风险。无论如何,使用已经实现此功能的库几乎肯定会更安全。

如果您对这类事情非常认真(坦率地说,这让我感到害怕),您肯定会希望将 ReactOS's heap implementation 作为 Microsoft 文档的补充。

【讨论】:

  • 使用 NTDLL 没有实际风险,正如微软希望人们相信的那样。
  • 使用未记录的 windows 功能的实际风险是真实存在的:没有人保证该功能在未来版本中仍然可用(并且具有相同的功能)。
  • 这似乎是直接使用 Windows 原生 API 的唯一方法。这不是好消息,但我会接受它作为正确答案。我将不得不使用 VirtualAlloc、VirtualFree 和自定义分配器来实现它。谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-05
  • 2019-10-05
  • 2014-05-10
  • 2012-06-02
  • 2014-07-12
相关资源
最近更新 更多