首页 > 解决方案 > VirtualAlloc() 的 _set_new_handler 等价物?

问题描述

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

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

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

标签: c++windowswinapi

解决方案


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

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

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

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

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

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

  • 您还可以使用地址窗口扩展来管理对 32 位应用程序的“大”分配的访问。

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

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


推荐阅读