相当于 VirtualAlloc() 的_set_new_handler?
Equivalent of _set_new_handler for VirtualAlloc()?
我有一个用于处理大型数据集的数据结构。它本质上充当磁盘上数据的"视图",根据请求从磁盘加载数据;它将尝试在内存中保留尽可能多的数据,以便在下次访问时不必从磁盘读取。当它检测到内存不足时,它会对引用计数为 0 的数据块进行"清理扫描"。它使用 _set_new_handler(( 来设置一个函数,当某些代码在某处尝试 malloc(( 内存但不能时调用此清理。这样,数据结构可以消耗尽可能多的内存,但当其他人需要一些内存时,它仍然会"退缩"。
现在我遇到了一些内存没有使用 malloc(((或 new(((分配的问题。我第一次在调用 CreateDIBSection(( 时开始看到它,我认为这是因为这个函数直接使用 VirtualAlloc((。因此,当分配失败时,不会调用新的处理程序,并且 VirtualAlloc 会失败。(我也有其他情况相同的情况,但我可以解决;所以CreateDIBSection((是我的主要"演示案例";但是使用该特定API解决不会解决我的一般问题(
所以我的问题是 - VirtualAlloc(( 是否有等效的 _set_new_handler((,或者另一种方式可以在 VirtualAlloc(( 失败时收到通知,以便我可以调用我的"清理内存"功能并再次尝试分配?或者,有没有办法拦截 VirtualAlloc(( 调用,以便我可以检查每个分配的内存可用性,并在必要时进行清理?谢谢。
内存"不应被视为基于现代虚拟内存的操作系统上的RAM - 它只是一个保留地址范围,可能由页面文件或其他一些映射文件视图支持。内存由操作系统根据需要分页进出 RAM,但实际上应将其视为磁盘而不是 RAM 分配。
在尝试构建用户模式内存"缓存"时,必须注意确保考虑到这一点,因为幼稚的尝试将导致净性能损失,因为实际上不会在 RAM 中缓存任何额外的内容,并且将有不必要的额外页面文件分配给页面输入和输出。
考虑到这一点,我可以建议:
使用MapViewOfFile(和相关API(创建文件"视图"。这为操作系统提供了最佳提示,即您正在查看的文件根据需要直接从其自己的字节分页到 RAM 中,并确保您不会浪费地将字节从源文件复制到页面文件中。
如果无法重新生成为 64 位应用,请使用应用上的/LARGE_ADDRESS_AWARE 链接器开关获取额外的 2GB 潜在 VM 分配。
确定分配的一些可配置限制:有关其他应用程序如何处理此问题的示例,请参阅 Java 运行时 -Xmx 标志。
还可以使用地址窗口化扩展插件来管理对来自 32 位应用的"大型"分配的访问。
或者考虑使用 64 位合作伙伴应用加载文件,然后使用共享文件节来管理 64 位应用所做的分配的共享窗口。
实际上,我认为使用文件映射来创建文件的视图(或多个视图(将最容易实现并提供合理的性能(如果不是最佳性能(-即使视图未在32位进程中映射,这并不意味着64位底层操作系统不能或不会将这些字节保留在其文件IO缓存中的RAM中。
- 为什么我无法更改"set<set>"循环中的值<int>
- 如果"new int"返回"int*",那么为什么"new int[n]"不返回"int**"?
- 对于set上的循环-获取next元素迭代器
- 有没有一种方法可以使用placement new将堆叠对象分配给分配的内存
- 重载运算符new[]的行为取决于析构函数
- 过载'operator new'如何导致无限循环?
- 创建具有 new in 函数和"this is nullptr"异常的对象
- Codelite C++ new project
- 在声明中合并两个常量"std::set"(不是在运行时)
- 有没有办法对std::unordered_set、std::unrdered_map、std::set、std::map
- 在类c++中使用new声明数组
- g++用户定义的动态链接库上的全局new和delete运算符
- 将 std::set 与基于键的比较器一起使用
- 如何使用set实现无序数据结构?
- 如果整个应用程序是虚拟映射的,为什么 new 会进行系统调用?
- 使用运算符调用 void 函数时出错<set>
- 在将 new 与指针一起使用时,创建数组的指定长度
- 修改"std::set"中用户定义类型的值
- 体系结构x86_64的未定义符号:std:terminate(),typeinfo,运算符delete[],运算符new
- 如何在c++中使用get和set方法来初始化一个用new初始化的对象?