释放 Windows 上C++ 'new'保留的虚拟内存

Releasing virtual memory reserved by C++ 'new' on Windows

本文关键字:保留 虚拟内存 new Windows 释放 C++      更新时间:2023-10-16

我正在编写一个32位.NET程序,它有两个阶段的输入过程:

  1. 它通过C++/CLI使用本机C++将无限数量的文件解析到相应的SQLite数据库中(所有数据库都具有相同的模式)。C++"new"的分配通常会消耗高达1GB的虚拟地址空间(2GB可用;我知道3GB的扩展,但这只会推迟问题的解决)。

  2. 它使用复杂的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压缩它并重用内存。