2

如果在堆栈上分配,Linux 在不再使用时不会回收内存。

我在堆上动态分配(malloc/mmap)1GB。

  • 分配前:

$顶部

虚拟内存 1GB

常驻内存 ~ 0

  • 内存集 1GB

$顶部

虚拟内存 1GB

常驻内存 1GB

  • 1GB 的 deallocate (free/munmap) - 按预期回收

$顶部

虚拟内存 1GB

常驻内存 ~ 0

我在堆栈上动态分配 1GB。

  • 前:

$顶部

虚拟内存 1GB

常驻内存 ~ 0

  • 内存集 1GB

$顶部

虚拟内存 1GB

常驻内存 1GB

  • 解除分配(堆栈展开) 1GB - 常驻内存仍然是 1GB,即使在解除分配之后!为什么?

$顶部

虚拟内存 1GB

常驻内存 1GB

为什么,当堆栈展开驻留内存时(物理页面仍在使用中)?

堆段分配是用 mmap 完成的,而堆栈段分配是用 mmap 完成的——那么为什么回收的行为会有所不同呢?

4

1 回答 1

3

因为操作系统认为一旦你使用了那么多堆栈,你可能会再次这样做。操作系统无法[从您的应用程序外部]真正知道您的应用程序将来要做什么。很难弄清楚什么时候可以释放一些堆栈,并且您在操作系统中会遇到各种有趣的竞争条件,您必须停止应用程序运行只是为了减少它的堆栈 - 然后它突然再次需要它,所以它需要被分配。

mmap另一方面,使用munmap可以告诉操作系统“我对这个内存没有兴趣”。所以它在那时被释放[作为 munmap 调用本身的一部分 - 具体来说,在zap_pte_range页面本身被释放并返回给操作系统。

除非满足以下条件,否则这应该不是什么大问题: 1. 您在没有交换的嵌入式系统上运行。2.您的应用程序在使用大量堆栈返回后运行了很长时间(假设您实际上确实需要这么多内存作为堆栈,您必须在需要时让该内存可用,所以它显然只是一个如果应用程序稍后不需要堆栈并且该时间段很长 - 无论您对 long 的定义是什么,都会出现问题。3. 您的系统没有足够的 RAM 来满足其他应用程序中的其他 RAM 需求。

我这么说的原因是,虽然堆栈使用了那么多内存,但如果应用程序长时间不使用内存,并且系统内存不足,它会将其交换到磁盘 - 进行交换如果需要,在稍后阶段。

我还要说,使用如此大量的堆栈空间通常被认为是一个坏主意。堆栈空间不足[达到限制或“没有足够的可用内存”]几乎总是致命的。

所以虽然我经常建议使用堆栈空间来存储临时变量,但我认为 1GB 的堆栈是相当多的。几兆字节应该是可以接受的,但数百兆字节或更多可能是“您可能应该以另一种方式存储东西”的标志。

于 2013-01-17T23:40:33.337 回答