释放 Windows 上C++ 'new'保留的虚拟内存
Releasing virtual memory reserved by C++ 'new' on Windows
我正在编写一个32位.NET程序,它有两个阶段的输入过程:
-
它通过C++/CLI使用本机C++将无限数量的文件解析到相应的SQLite数据库中(所有数据库都具有相同的模式)。C++"new"的分配通常会消耗高达1GB的虚拟地址空间(2GB可用;我知道3GB的扩展,但这只会推迟问题的解决)。
-
它使用复杂的SQL查询(从C#运行)将数据库合并到一个数据库中。我将合并后的数据库的cache_size设置为1GB,以便合并部分的页面错误最小。
我的问题是,第2阶段的缓存没有重用"new"分配的1GB内存,而第1阶段的"delete"则正确释放了1GB内存。我知道没有泄漏,因为在离开第1阶段后,"私有字节"立即下降到我预期的较低数量然而,"虚拟大小"仍然保持在C++使用的峰值左右。
C++和SQLite缓存之间的这种不共享导致我耗尽了虚拟地址空间。如何解决此问题,最好是以符合标准的方式解决?我真的很想把C++分配的内存放回操作系统。
这不是您可以从C++抽象级别有效控制的事情(换句话说,您无法确定程序释放到C++运行时的内存是否会释放到操作系统)。使用特殊的分配策略和非标准扩展来尝试处理这个问题可能无论如何都不起作用,因为您无法控制使用的外部库如何处理内存(例如,如果有缓存的数据)。
一个可能的解决方案是将C++部分移动到外部进程,该进程在创建SQLite数据库后终止。拥有一个外部进程会带来一些麻烦(例如,对发生的事情保持"实时"控制有点困难),但也会带来更多的可能性,比如并行处理,即使库不支持多线程或通过网络使用多台机器。
由于您与C++/CLI进行互操作,因此您可能正在使用Microsoft的编译器。
如果是这样的话,那么您可能需要查找_heapmin
。从"stage 1"退出后,调用它,它会将C++堆管理器持有的内存块释放回操作系统,如果从操作系统分配的整个内存块现在是空闲的。
在Linux上,我们使用了googlemalloc(http://code.google.com/p/google-perftools/)。它具有向操作系统释放空闲内存的功能:MallocExtension::instance()->ReleaseFreeMemory()
。
理论上,gcmalloc可以在Windows上运行,但我个人从未在那里使用过它。
您可以从C#的GC中分配它,固定它,使用它,然后允许它返回,从而释放它,让GC压缩它并重用内存。
- 必须为 C++20 协程帧保留多少内存?
- 了解 Linux 虚拟内存:valgrind 的 massif 输出显示了有和没有 --pages-as-heap 的主要差异
- 为什么我只能在 4 GB 的虚拟内存空间上分配 2 GB?
- AWS pandas 安装出现错误:虚拟内存已耗尽:无法分配内存
- 堆内存,所有保留的内存由noscript_shared_function_infos持有
- 如何写入为结构保留的内存位置
- 如何判断虚拟内存页是否已锁定
- 如何使用一个 VirtualFree 调用删除多个相邻的虚拟内存分配?
- std::unordered_set::保留容器内存要求的角色?
- Windows 32 位 mfc 应用程序的虚拟内存中的地址
- 如何将x64机器代码写入虚拟内存并在C++中为Windows执行
- 读取虚拟内存时C++缓冲区溢出
- 在 Linux C++ 中获取虚拟内存最大映射计数
- GlobalMemoryStatusEx() 提供的总虚拟内存为 127 TB
- 在虚拟内存中分配大型类C
- 无法保留指向内存的指针
- 将保留在内存中传递的变量的副本
- 如何确定为我的程序保留了多少虚拟内存
- 为什么保留的虚拟内存会增长,而当前正在使用的虚拟内存不会增长?
- 释放 Windows 上C++ 'new'保留的虚拟内存