我的 Windows/C++ 应用程序使用操作员在内存中分配 ~1Gb 的数据new
并处理这些数据。处理后数据被删除。
我注意到,如果我在不退出应用程序的情况下再次运行处理,则对操作员的第二次调用以new
分配 ~1Gb 的数据会失败。
我希望 Windows 能够将内存返回。这可以通过其他一些 Win32 调用等以更好的方式进行管理吗?
我的 Windows/C++ 应用程序使用操作员在内存中分配 ~1Gb 的数据new
并处理这些数据。处理后数据被删除。
我注意到,如果我在不退出应用程序的情况下再次运行处理,则对操作员的第二次调用以new
分配 ~1Gb 的数据会失败。
我希望 Windows 能够将内存返回。这可以通过其他一些 Win32 调用等以更好的方式进行管理吗?
我认为这不是 Windows 问题。检查您是否正确使用了 delete 或 delete[]。如果您发布分配/释放内存的代码,也许会有所帮助。
在大多数运行时环境中,从操作系统分配给应用程序的内存保留在应用程序中,并且很少返回给操作系统。释放内存块允许您在应用程序内重用该块,但不会将其释放到操作系统以使其可用于其他应用程序。
Microsoft 的 C 运行时库尝试通过 _heapmin_region 调用 _heap_free_region 或 _free_partial_region 将内存返回给操作系统,后者调用 VirtualFree 将数据释放到操作系统。但是,如果相应区域中的整个页面不为空,则它们不会被释放。造成这种情况的一个常见原因是 C++ 容器的簿记信息和存储缓存。
这可能是由于内存碎片(实际上是地址空间碎片)造成的,其中各种因素导致您的程序地址空间没有可用的 1gb 连续孔。实际上,我怀疑您的内存管理中存在错误(抱歉)-您是否通过泄漏检测运行代码?
由于您使用的是非常大的内存块,您应该考虑使用VirtualAlloc()和VirtualFree(),因为它们允许您直接分配和释放页面,而无需与堆管理器交互的开销(内存和时间)。
由于您使用的是 C++,因此值得注意的是,您可以使用Placement new在以这种方式分配的内存中构造 C++ 对象。
这个问题几乎可以肯定是内存碎片。在 32 位 Windows 上,您可以分配的最大连续区域约为 1.1GB(因为 EXE 中的各种 DLL 会阻止更大的连续区域可用)。如果在取消分配内存分配(或 DLL 加载,或内存映射文件)后,最终位于您之前的 1GB 区域的中间,那么将不再有 1GB 区域可用于您下次调用 new 以分配 1GB。因此它会失败。
您可以使用VM Validator可视化此过程。