我在测试程序中观察以下行为:
我正在使用1 MB的malloc()
,然后在sleep(10)
之后进行free()
。我正在做五次。我在程序运行时观察top
中的内存消耗。
一旦free()
-D,我希望该程序的虚拟内存(VIRT)消耗量会减少1  MB。但实际上不是。它保持稳定。这种行为的解释是什么?malloc()
在分配内存时会做一些储备吗?
一旦
free()
-D,我期望程序的虚拟内存(firt)消耗会被1MB降低。
好吧,这不能由C标准保证。它只说,一旦您 free()
存储器,就不应再访问它。
是否实际返回到可用的内存池还是保留以将来分配的存储器块由内存管理器决定。
C标准不强迫malloc
和free
的实现者直接将存储器直接返回到OS。因此,不同的C库实现将以不同的方式行事。他们中的一些人可能会直接退还,有些可能不会。实际上,相同的实现也将根据分配规模和模式的不同。
当然,这种行为是有充分理由的:
- 并非总是可能的。OS级内存分配通常在页面(4KB,4MB或...大小)中进行。如果在释放另一部分后仍在使用页面的一小部分,则该页面才能将页面归还到操作系统,直到该部分也被释放。
- 效率。应用程序很可能会再次要求内存。那么,为什么还要把它还给操作系统,并在不久之后再次要求。(当然,可能对存储器的大小有一个限制。)
在大多数情况下,如果实现决定保留它,则您对free
的内存不负责(假设这是一个很好的实现)。迟早它将重新分配或返回到操作系统。因此,对内存使用的优化应基于您具有malloc
-ED的数量,并且您还没有free
-D。您必须担心这一点的情况是,当您的分配模式/尺寸开始引起记忆片段时,这本身就是一个很大的话题。
但是,如果您在嵌入式系统上,并且可用的内存量受到限制,并且您需要对何时/如何分配和释放内存进行更多控制手动。
编辑:我没有解释您为什么不对内存负责。原因是,在现代操作系统上,分配的内存是虚拟的。这意味着,如果您在32位系统或64位系统的10TB上分配512MB,只要您不读取或写入该内存,它就不会为此保留任何物理空间。实际上,它只会为您从该大块而不是整个块中触摸的页面保留物理内存。在"不使用该内存的时间"之后,其内容将被复制到磁盘,而基础的物理内存将用于其他物体。
这非常依赖于使用的实际malloc实现。
在Linux下,有一个阈值(MMAP_THRESHOLD
)来确定给定malloc()
请求的内存来自何处。
如果请求的金额低于或等于MMAP_THRESHOLD
,则可以通过从所谓的"免费列表"中获取请求,如果任何内存块已经是free()
d。否则,该程序的"断路线"(即数据段的末尾)增加了,并且该过程为程序提供的记忆用于请求。
在free()
上,将释放的内存块添加到免费列表中。如果数据段末尾有足够的自由存储器,则再次移动断路线(上面提到)以缩小数据段,将多余的内存返回到OS。
如果请求的金额超过MMAP_THRESHOLD
,则OS请求单独的内存块,并在free()
期间再次返回。
另请参见https://linux.die.net/man/3/malloc有关详细信息。