Visual C++运行时的malloc/free函数会将内存返回给操作系统吗?

6

这个问题与malloc实现是否会将已释放的内存返回给系统?非常相似,但我对Windows / Microsoft Visual Studio的答案和有关确切虚拟内存状态的细节很感兴趣。

Visual C++ CRT free会将内存返回给系统吗?在虚拟内存分配方面,内存的确切状态是什么?在释放大块内存后,该块内存中的内存是提交的、保留的还是空闲的?如果我在释放后调用_heapmin会怎样?


3
free会将其返回给运行时内存分配器。之后会由内存分配器决定接下来的处理方式。有时它会归还给系统,有时它会继续保留并尝试重用。 - David Heffernan
1
此外,MSVC附带了CRT的源代码,因此您可以自行检查并阅读它调用的Win32 API函数。 - user786653
你真正需要关注的是释放你分配的内存,而将其他堆管理工作留给操作系统。 - C.J.
@C Johnson:这对于许多应用程序可能是正确的,但并非所有应用程序都是如此。在我的情况下,我需要担心虚拟内存消耗,因为应用程序使用的系统组件(即Direct3D资源分配,但可能还有其他组件)直接使用虚拟内存,而不是使用malloc/free。如果堆耗尽了虚拟内存,就会导致无法恢复的错误,因为无论我的应用程序释放多少内存,由于没有可用的虚拟内存,Direct3D仍将失败。 - Suma
2个回答

9

检查2010年的源代码,可以看到直接调用HeapAlloc/HeapFree Win32 API函数来使用malloc/free,其中由运行时创建的_crtHeap作为堆。因此,对于VS 2010和最近的Windows版本(Win2000、WinXP、Vista、Win7)的答案是:

通过free释放的内存被返回给操作系统,但仍然保留。

Heap Functions documentation中关于内存承诺如何处理的说明如下:

HeapCreate函数创建一个私有堆对象,调用进程可以通过使用HeapAlloc函数分配内存块。...如果HeapAlloc的请求超过了已提交页面的当前大小,并且物理存储可用,则会自动从此保留空间中提交其他页面。一旦提交了页面,它们在进程终止或通过调用HeapDestroy函数销毁堆之前不会被取消提交。此外,HeapCreate documentation 还指出了以下关于没有设置最大大小的堆的情况:

如果dwMaximumSize为0,则堆的大小可以增长。堆的大小仅受可用内存限制。对于大于固定大小堆限制的内存块的分配请求不会自动失败; 相反,系统将调用VirtualAlloc函数来获取所需的内存。需要分配大内存块的应用程序应将dwMaximumSize设置为0。

我没有找到任何关于释放使用VirtualAlloc分配的块是否以特殊方式处理的信息,可能需要进行实验才能知道。

关于_heapmin,在VS 2010中不起作用,因为它只调用HeapCompact,而CRT堆没有关闭自动合并的空闲块。因此,_heapmin的文档似乎是错误的,很可能是来自某个旧版本的运行时。

2
不会,它不会将内存返回给“系统”。_heapmin仅释放空的整个页面,并且通常没有太大作用。它不会在页面之间移动数据。因此,根据释放堆中内存的位置,使用free()和_heapmin的组合是否实际减少正在使用的页面数量取决于哪里。还要注意,VS为Debug和Release使用不同的堆。
要获得更多控制,请参见HeapCreate()/HeapAlloc()等API。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接