如果/何时取消分配的堆内存得到回收?

我一直在embedded式Linux系统上运行一夜的内存testing。 使用vmstat我已经观察到,随着时间的推移,空闲内存会稳步下降。 根据procfs中的一些分析,一个进程的堆栈大致以相同的速度增长。 我怀疑有内存泄漏,并在代码中发现了一些经常使用newdelete位置。 但是,我没有看到没有匹配delete调用的new调用。

我再次运行内存testing,今天早上通过以下调用清除了内存caching

 echo 3 > /proc/sys/vm/drop_caches 

vmstat中列出的可用内存下降到接近testing开始时的值。

内核是否定期回收未使用的堆页? 如果是这样,除了上面的那个,还有其他的时间呢? 空闲内存可能低于某个阈值时

Solutions Collecting From Web of "如果/何时取消分配的堆内存得到回收?"

正如其他人所说,这个进程有责任把内存返回给内核。

通常有两种方式分配内存:如果malloc() / new是一个大于一定大小的内存块,内存将通过mmap()从操作系统中分配出来,一旦空闲就会被清除。 较小的块通过向上移动sbrk边界来增加进程的数据区域来分配。 只有在该段末尾有一定大小的块空闲时才能释放该内存。

例如:(伪代码,我不太了解C ++)

 a = new char[1000]; b = new char[1000]; 

内存映射:

 ---------------+---+---+ end of program | a | b | ---------------+---+---+ 

如果你现在有空,中间有一个洞。 它不能被释放,因为它不能被释放。 如果你释放b ,这个进程的内存可能减少也可能不减少; 未使用的余数返回给系统。

一个简单的程序测试

 #include <stdlib.h> int main() { char * a = malloc(100000); char * b = malloc(100000); char * c = malloc(100000); free(c); free(b); free(a); } 

导致像一个strace输出

 brk(0) = 0x804b000 brk(0x8084000) = 0x8084000 brk(0x80b5000) = 0x80b5000 brk(0x809c000) = 0x809c000 brk(0x8084000) = 0x8084000 brk(0x806c000) = 0x806c000 

显示brk值首先增加(对于malloc() ),然后再次减小(对于free() )。

内核将在需要的时候回收缓存的内存页面,也就是系统在内存不足时运行。 进程的堆(自由存储)中的内存页是否被返回到操作系统是由进程的内存管理器决定的,在这种情况下是C ++库中的new / delete实现。 这是一个完全自愿的操作,内核无关。

drop_caches做的窍门,你可以推断出它是内核缓存,而不是进程的堆,这是填补内存。 使用free命令可以找出有多少内存可用于应用程序,尤其是, 它报告的-/+ buffers/cache行。

在程序中调用delete会导致内存返回到程序运行时的内存管理器。 原则上可以这样写,以便将释放的内存返回到操作系统,但是如果确实如此,我会感到惊讶。 而是将回收的内存留在旁边,以便随后调用new内存。

请注意,这是您的流程的虚拟内存。 在程序执行期间,实际上在物理存储器中实际存在多少取决于整个系统负载,并由操作系统来处理。

用户调用malloc和free(或new和delete),据我所知,永远不会将不再使用的页面返回给O / S。 相反,他们只记得释放了什么内存,所以如果你做了一个malloc /新的大小,可以通过以前释放的内存来满足,那么它将使用它,而不是去O / S和使用sbrk来获得更多的记忆。

因此这个代码:

 for (;;) { struct { char data[200 * 1024 * 1024] } HugeBuffer; HugeBuffer *buff = new HugeBuffer; delete buff; } 

一次将分配200Mb,然后永远稳定地使用这个内存。 它将在原始分配中一次转到O / S,然后在用户空间循环摆弄。