我一直在运行的嵌入式Linux系统上过夜的内存测试。 使用vmstat我观察到,可用内存随时间稳步下降。 根据一些procfs的分析smaps,一个进程的堆增长以大致相同的速率。 我怀疑内存泄漏,发现在代码中的几个景点new
和delete
是经常使用的。 不过,我没有看到一个new
不匹配呼叫delete
通话。
我再次运行内存测试和今天上午清除与以下调用的内存缓存
echo 3 > /proc/sys/vm/drop_caches
在vmstat的列出的可用内存下降到接近时开始试验的值。
请问内核定期回收未使用的堆页? 如果是这样,有没有除了一个上面这样做是其他时间? 大概是免费的,当内存低于一定的阈值?
正如有人说,这是该过程的责任返回内存的内核。
通常有2种方式来分配内存:如果你malloc()
/ new
具有一定规模的一个内存块,内存被从操作系统分配通过mmap()
,一旦它是免费的eturned。 更小的块被通过移动增加过程的分配存储区域sbrk
向上边界。 如果超过特定大小的块是自由在该段的末尾该存储器只释放。
例如:(伪代码,我不知道C ++非常好)
a = new char[1000];
b = new char[1000];
存储器映射:
---------------+---+---+
end of program | a | b |
---------------+---+---+
如果你释放a
现在,你在中间有一个洞。 它不被释放,因为它不能被释放。 如果您免费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()
当它需要他们,即当系统本来耗尽内存的内核将回收缓存的内存页面。 无论是从工艺的堆(免费店)内存页是不断返回到操作系统在进程的内存管理的自由裁量权,在这种情况下, new
/ delete
在C ++库实现。 这是与内核无关的一个完全自愿的操作。
从事实drop_caches
的伎俩,可以推断,这是内核缓存,而不是过程的堆,这是填补了记忆。 使用free
命令找出多少内存实际可用的应用程序使用,ESP。 在-/+ 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曾经在原始分配,然后循环在用户空间摆弄周围。