C++ 与VirtualAlloc()的\u set\u new_u处理程序等价?

C++ 与VirtualAlloc()的\u set\u new_u处理程序等价?,c++,windows,winapi,C++,Windows,Winapi,我有一个用于处理大型数据集的数据结构。它本质上充当磁盘数据的“视图”,根据请求从磁盘加载数据;它将尽量在内存中保留尽可能多的数据,以便下次访问时,它不必从磁盘读取数据。当它检测到内存不足时,它会对引用计数为0的数据块进行“清理扫描”。它使用_set_new_handler()来设置一个函数,当某些代码在某处尝试调用malloc()内存但无法执行时,该函数将调用此清理。这样,数据结构可以消耗尽可能多的内存,但当其他人需要一些内存时,仍然会“后退” 现在我有一个问题,就是没有使用malloc()或n

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

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

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

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

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

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

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

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

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

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

  • >P>或考虑使用一个加载文件的64位伙伴应用程序,然后使用一个共享窗口管理64位应用程序的分配。


实际上,我认为使用文件映射来创建一个(或多个)视图即使在32位进程中没有映射视图,但这并不意味着64位底层操作系统不能或不会将这些字节保留在其文件IO缓存的RAM中。

CreateDIBSection
不调用
VirtualAlloc
或在用户内存中分配任何内存模式并且在
VirtualAlloc
ot
NtAllocateVirtualMemory
上不存在通知处理程序。只有你们自己在这个api上设置了钩子,当你们不传递一个hSection时,CreateDIBSection如何分配内存?还有其他低级内存分配方法吗?它们从内核调用
nAllocateVirtualMemory
。当您为BitMapi调用
DeleteObject
时,内存将可用这是一个32位的应用程序吗?如何将虚拟内存耗尽以分配?我猜你也在RAM中锁定了页面?在虚拟内存操作系统(如windows)上,“内存”指的是分配有地址的东西,但可能在RAM或磁盘上,所以你似乎发明了一种复杂的方法,让你的应用程序崩溃,但却一事无成。几乎所有其他此类行为都依赖于启动时分配的固定大小的缓冲区。请参阅Java的-Xmx标志。您可能希望尝试使用大型地址感知交换机构建应用程序,以获得额外的2GB虚拟机地址空间(假设至少有64位操作系统)。但是,有了10yo代码,谁能知道它是否真的能识别大地址呢?从技术上讲,这并不是这个问题的答案。