我在我的测试程序中观察到以下行为:
我正在做malloc()
为1 MB然后free()
它在sleep(10)
之后。我这样做了五次。我在程序运行时观察top
中的内存消耗。
一旦free()
-d,我预计该程序的虚拟内存(VIRT)消耗将减少1 MB。但实际上并非如此。它保持稳定。这种行为有什么解释? malloc()
在分配内存时做了一些保留吗?
一旦
free()
-d,我预计程序的虚拟内存(VIRT)消耗将减少1MB。
嗯,这不是C标准所保证的。它只是说,一旦你了解内存,你就不应该再访问它了。
内存块是否实际返回到可用内存池或保留在一边以供将来分配,由内存管理器决定。
C标准不强制free()
和malloc
的实现者直接将内存返回给操作系统。因此,不同的C库实现将表现不同。他们中的一些人可能会直接退回,有些人可能不会。实际上,根据分配大小和模式,相同的实现也会表现不同。
当然,这种行为有充分的理由:
在大多数情况下,如果实现决定保留它,你不会对free
的内存负责(假设它是一个很好的实现)。迟早它将被重新分配或返回操作系统。因此,优化内存使用应该基于你有free
-ed的数量,你没有malloc
-d。您需要担心的情况是,您的分配模式/大小开始导致内存碎片,这本身就是一个非常大的主题。
但是,如果您在嵌入式系统上并且可用内存量有限,并且您需要更多地控制何时/如何分配和释放内存,则需要直接从操作系统请求内存页并手动管理。
编辑:我没有解释为什么你不对你自由的记忆负责。原因是,在现代操作系统中,分配的内存是虚拟的。这意味着如果您在32位系统或10TB的64位系统上分配512MB,只要您不读取或写入该内存,它就不会为其保留任何物理空间。实际上,它只会为您从该大块而不是整个块触摸的页面保留物理内存。在“一段时间不使用该内存”之后,其内容将被复制到磁盘,底层物理内存将用于其他内容。
这非常依赖于使用中的实际malloc实现。
在Linux下,有一个阈值(free
)来决定给定MMAP_THRESHOLD
请求的内存来自何处。
如果请求的数量低于或等于malloc()
,则通过从所谓的“空闲列表”中获取该请求,如果任何内存块已经是MMAP_THRESHOLD
d,则满足该请求。否则,程序的free()
(即数据段的结尾)增加,并且通过该过程使程序可用的存储器用于请求。
在"break line"上,释放的内存块被添加到空闲列表中。如果在数据段的最末端有足够的可用内存,则再次移动中断线(上面提到)以缩小数据段,将多余的内存返回到OS。
如果请求的数量超过free()
,则OS会请求单独的内存块,并在MMAP_THRESHOLD
期间再次返回。
有关详细信息,请参阅free()
。