【问题标题】:Equivalent of _set_new_handler for VirtualAlloc()?VirtualAlloc() 的 _set_new_handler 等价物?
【发布时间】:2018-09-10 11:22:40
【问题描述】:

我有一个用于处理大型数据集的数据结构。它本质上充当磁盘数据的“视图”,根据请求从磁盘加载数据;它将尝试在内存中保留尽可能多的数据,以便在下次访问时不必从磁盘读取。当它检测到内存不足时,它会对引用计数为 0 的数据块进行“清理扫描”。它使用 _set_new_handler() 设置一个函数,当某些代码在某处尝试 malloc() 内存但可以不。这样,数据结构可以消耗尽可能多的内存,但在其他人需要一些内存时仍会“退避”。

现在我遇到了一些内存没有使用 malloc()(或 new())分配的问题。我第一次在调用 CreateDIBSection() 时开始看到它,我认为这是因为这个函数直接使用了 VirtualAlloc()。因此,当分配失败时,不会调用新的处理程序,而 VirtualAlloc 只会失败。 (我也有其他情况相同的情况,但我可以解决这些问题;所以 CreateDIBSection() 是我主要的问题“演示案例”;但使用该特定 API 解决问题并不能解决我的一般问题)

所以我的问题是 - VirtualAlloc() 是否有等效的 _set_new_handler() 或 VirtualAlloc() 失败时通知的另一种方式,以便我可以调用我的“清理内存”功能并再次尝试分配?或者,有没有办法拦截 VirtualAlloc() 调用,以便我可以检查每次分配的内存可用性,并在必要时进行清理?谢谢。

【问题讨论】:

  • CreateDIBSection 不调用VirtualAlloc 或在用户模式下分配任何内存。并且在VirtualAlloc ot NtAllocateVirtualMemory 上不存在通知处理程序。只有你们自己设置了这个 api 的钩子
  • 当你没有通过 hSection 时 CreateDIBSection 是如何分配内存的?还有其他低级内存分配方法吗?
  • 他们从内核调用NtAllocateVirtualMemory。您调用DeleteObject 获取位图时,内存将是空闲的
  • 这是 32 位应用程序吗?你怎么用完了虚拟内存来分配?而且我认为您还将页面锁定在 RAM 中?在虚拟内存操作系统(例如 Windows)上,“内存”是指分配了地址的东西,但可能在 RAM 或磁盘上,因此您似乎发明了一种复杂的方法来使您的应用程序在实现时中断绝对没有。
  • 几乎所有此类行为的其他实例都依赖于在启动时分配的固定大小的缓冲区。请参阅 Java 的 -Xmx 标志。您可能想尝试使用 Large Address Aware 开关构建您的应用程序,以提供额外的 2GB VM 地址空间(假设至少是 64 位操作系统)。但是,使用 10yo 代码 - 谁能判断它是否真的会感知大地址......

标签: c++ windows winapi


【解决方案1】:

“内存”不应被理解为现代基于虚拟内存的操作系统上的 RAM - 它只是一个保留的地址范围,可能由页面文件或其他映射文件视图支持。内存会根据操作系统的需要调入和调出 RAM,但实际上应该将其视为磁盘而不是 RAM 分配。

在尝试构建用户模式内存“缓存”时必须注意确保考虑到这一点,因为幼稚的尝试将导致净性能损失,因为实际上不会在 RAM 中缓存任何额外的页面文件,并且将不必要的额外页面文件分配给进出页面。

考虑到这一点,我可以建议:

  • 使用 MapViewOfFile(和相关 API)创建文件“视图”。这为操作系统提供了最佳提示,即您正在查看的文件根据需要直接从其自己的字节分页到 RAM 中,并确保您不会浪费地将字节从源文件复制到页面文件。

    李>
  • 如果您无法重建为 64 位应用程序,请使用应用程序上的 /LARGE_ADDRESS_AWARE 链接器开关以获得额外 2GB 的潜在 VM 分配。

  • 确定一些可配置的分配限制:请参阅 Java 运行时 -Xmx 标志,了解其他应用程序如何处理此问题的示例。

  • 您还可以使用 Address Windowing Extensions 管理对 32 位应用程序的“大型”分配的访问。

  • 或者考虑使用加载文件的 64 位合作伙伴应用程序,然后使用 Shared File Sections 管理共享窗口,以了解 64 位应用程序所做的分配。

务实地,我认为使用文件映射来创建文件的一个(或多个)视图将是最容易实现的,并且即使不是最佳性能也能提供合理的性能 - 即使视图未在您的 32 位进程中映射,这并不意味着64 位底层操作系统不能或不会将这些字节保留在 RAM 中的文件 IO 缓存中。

【讨论】:

  • 从技术上讲,这不是问题的答案。
猜你喜欢
  • 2016-06-25
  • 2020-10-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多