malloc在分配内存时是否保留更多空间?

use*_*352 31 c malloc free dynamic-memory-allocation

我在测试程序中观察到以下行为:

我正在malloc()为1 MB,然后free()之后sleep(10)。我做了五次。我正在观察top程序运行时的内存消耗。

一次free()-d,我期望程序的虚拟内存(VIRT)消耗将减少1 MB。但实际上并非如此。它保持稳定。这种现象的解释是什么?malloc()分配内存时是否做一些保留?

Sou*_*osh 42

一次free()-d,我期望程序的虚拟内存(VIRT)消耗将减少1MB。

好吧,这不是C标准所保证的。它只是说,一旦您free()有了内存,就不应该再访问它了。

内存管理器决定是将内存块实际返回到可用内存池,还是留作以后的分配。

  • @ user1228352不,C语言不允许这样做。如果需要更多控制,则需要实现自己的依赖于平台特定的OS系统调用的内存管理器。 (8认同)
  • @ user1228352我理解这之后的感觉,让我们说个诡计,但是-您真的不想走那条路,从长远的角度来看也没有道理,因为这只是浪费时间来弄清楚如何制作自己的内存管理器(如果操作系统允许)并进行调试。遵循C标准,您将拥有更加舒适的体验,而OS则可以满足您的需求。好吧,除非您的目标是制作自己的操作系统,否则您可能不会问这个问题。 (8认同)
  • 您为什么要减少不必要的消耗呢?如果您想获得有用的答案,应该向我们详细介绍您的环境。一些不寻常的环境也有不寻常的`malloc`和`free`实现。如果您遇到了实际问题(这不仅仅是表面上的问题),则可以用一个永远不拥有任何额外虚拟内存的分配器替换该分配器,但是有大约99%的机会由于碎片等问题而使情况变得更糟。 (2认同)

Ame*_*een 28

C标准并不强制上的实施者mallocfree对内存直接返回给操作系统。因此,不同的C库实现将表现不同。他们中有些人可能会直接将其还给他人,有些则可能不会。实际上,同一实现也将根据分配大小和模式而有所不同。

当然,此行为是有充分理由的:

  1. 并非总是可能的。操作系统级内存分配通常以页面(一次4KB,4MB或...大小)完成。并且,如果在释放另一部分之后仍在使用页面的一小部分,则在该部分也被释放之前,无法将页面退还给操作系统。
  2. 效率。应用程序很可能会再次请求内存。那么,为什么要把它还给操作系统并在不久后再次要求它。(当然,所保留的内存大小可能有限制。)

在大多数情况下,free如果实现决定保留该内存,则无需为内存负责(假设它是一个好的实现)。迟早将其重新分配或返回给OS。因此,针对内存使用情况的优化应基于malloc-ed和未free-d的数量。您必须担心的情况是,您的分配模式/大小开始引起内存碎片,这本身就是一个很大的话题。

但是,如果您使用的是嵌入式系统,则可用的内存量有限,并且您需要更多地控制何时分配内存以及如何释放内存以及如何释放内存,那么您需要直接从OS请求内存页并手动进行管理。

编辑:我没有解释为什么您不负责您释放的内存。原因是,在现代OS上,分配的内存是虚拟的。这意味着,如果您在32位系统或10TB 64位系统上分配512MB,只要您不对该内存进行读写操作,它将不会为其保留任何物理空间。实际上,它只会为您从那个大块而不是整个块中触摸的页面保留物理内存。并且在“一段时间不使用该内存”之后,其内容将被复制到磁盘,并且基础物理内存将用于其他用途。


glg*_*lgl 12

这非常取决于所使用的实际malloc实现。

在Linux下,有一个阈值(MMAP_THRESHOLD)来确定给定malloc()请求的内存来自何处。

如果请求的数量小于或等于MMAP_THRESHOLD,则可以通过从所谓的“空闲列表”中获取请求来满足请求(如果已经存储了任何存储块)free()。否则,将增加程序的“换行”(即数据段的末尾),并且将通过此过程提供给程序的内存用于请求。

在上free(),已释放的内存块被添加到空闲列表中。如果数据段的末尾有足够的可用内存,则再次移动折线(上面已提及)以缩小数据段,将多余的内存返回给OS。

如果请求的数量超过MMAP_THRESHOLD,操作系统将请求一个单独的存储块,并在期间再次返回free()

另请参阅https://linux.die.net/man/3/malloc