C++ 释放C+保留的虚拟内存+';新';在窗户上

C++ 释放C+保留的虚拟内存+';新';在窗户上,c++,windows,memory,memory-management,C++,Windows,Memory,Memory Management,我正在编写一个32位.NET程序,具有两个阶段的输入过程: >P>使用C++ C++语言将原生C++解析为相应的SQLite数据库(所有的模式都相同)。C++的“新”分配通常消耗1GB的虚拟地址空间(2GB可用;我知道3GB扩展,但这将延迟问题)。 它使用复杂的SQL查询(从C#运行)将数据库合并到单个数据库中。我将合并数据库的缓存大小设置为1GB,以便合并部分的页面错误最小 我的问题是,第2阶段中的缓存没有重用由“new”分配的1GB内存,而由第1阶段中的“delete”正确释放。我知道没有

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

>P>使用C++ C++语言将原生C++解析为相应的SQLite数据库(所有的模式都相同)。C++的“新”分配通常消耗1GB的虚拟地址空间(2GB可用;我知道3GB扩展,但这将延迟问题)。

  • 它使用复杂的SQL查询(从C#运行)将数据库合并到单个数据库中。我将合并数据库的缓存大小设置为1GB,以便合并部分的页面错误最小

  • 我的问题是,第2阶段中的缓存没有重用由“new”分配的1GB内存,而由第1阶段中的“delete”正确释放。我知道没有泄漏,因为在离开第1阶段后,“私有字节”立即下降到我预期的较低数量然而,虚拟尺寸仍然是C++使用的最高值。
    <>这个C++与SQLite缓存之间的非共享导致我耗尽了虚拟地址空间。我如何解决这个问题,最好是以符合标准的方式解决?我真的想释放C++分配给内存的内存。这是不是你可以从C++抽象级别有效地控制的(换句话说,你不能确定你的程序释放到C++运行时的内存是否会被释放到OS)。使用特殊的分配策略和非标准扩展来处理此问题可能无论如何都不起作用,因为您无法控制所使用的外部库如何处理内存(例如,如果库中有缓存数据)


    一个可能的解决方案是将C++部分移到外部的“强>进程,一旦创建了SQLite数据库,该终止就结束。拥有一个外部进程会带来一些麻烦(例如,对发生的事情进行“实时”控制有点困难),但也会带来更多的可能性,如并行处理,即使库不支持多线程或通过网络使用多台计算机。

    因为您正在与C++/CLI进行互操作,您可能正在使用Microsoft的编译器


    如果是这样,那么您可能需要查找
    \u heapmin
    。当你退出“阶段1”后,调用它,它将释放C++堆管理器保存的内存块,如果从OS中分配的完整块现在是空闲的。在Linux上使用<谷歌>http://code.google.com/p/google-perftools/). 它有一个向操作系统释放可用内存的函数:
    MallocExtension::instance()->ReleaseFreeMemory()


    理论上,gcmalloc可以在Windows上工作,但我个人从未在Windows上使用过。

    您可以从C#的GC中分配它,固定它,使用它,然后允许它返回,从而释放它,让GC压缩它并重新使用内存。

    为什么不在64位操作系统上运行它呢?C++/CLI不是“原生C++”。它是.NET版本的C++,大概使用垃圾回收器,就像所有其他.NET语言一样。垃圾收集器很方便,但它们的缺点是您无法控制何时释放内存。我不确定它是否能解决您的问题,但可能会有所帮助:请查看GC.AddMemoryPressure()。这允许你指示CLR关于本地内存的使用,以便它可以更好地安排GC活动。@马克:至少在我读到的时候,他使用C++/CLI在程序的大部分(C语言)和本地C++之间“桥接”。Jalf说:“添加更多虚拟内存!”它是免费的!我使用本地C++和GUI之间的周期性回调来支持优美的用户取消和进度更新。用IPC这样做似乎很痛苦。不过我可能会调查一下。真的IPC有点烦人。在我们公司,我们开发了一个自定义层,试图减轻一点IPC。。。显然,在您的情况下,外部流程可能无法在其他项目中重复使用,因此可能是最简单的方法可能更有意义。尽管我不喜欢这两个答案中的任何一个,但这是我接受的答案。:)IPC方法的侵入性要比自定义分配器方法小得多。谢谢你的洞察力。我试过这个;它对“虚拟大小”没有影响。大概是因为“完整块”仍在部分使用中(可能是由C++中的某些单例使用)。我发现了一个类似的问题,其中提到了VMMap,后来我用它来说明问题的严重性。基本上,我认为我正在遭受堆碎片的困扰(如果这是正确的术语)。我有一堆16mb的堆,其中许多只有100-400KB。但我没想到还有这么多本机内存被分配,所以可能有一些小漏洞。@Matt:这听起来很合理(尽管无疑很难修复)。一种可能是为您已知的“大”内存用户提供分配器,这样他们的内存就与其他内存分开,当您使用完这些内存后,您就会知道这些内存块将是空的。