6

我一直在嵌入式 Linux 系统上运行通宵内存测试。使用 vmstat 我观察到可用内存随着时间的推移稳步减少。根据procfs中的一些smaps分析,一个进程的堆以大致相同的速度增长。我怀疑是内存泄漏,并在代码中发现了一些经常使用的地方。但是,我没有看到没有匹配呼叫的呼叫。newdeletenewdelete

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

echo 3 > /proc/sys/vm/drop_caches

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

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

4

4 回答 4

5

正如其他人所说,将内存返回给内核是进程的职责。

通常有两种分配内存的方法:如果您malloc()/new内存块超过一定大小,则内存会从操作系统通过分配,mmap()并在空闲时立即返回。sbrk通过向上移动边界来增加进程的数据区域来分配较小的块。只有在该段末尾有超过一定大小的块空闲时,才会释放此内存。

eg:(伪代码,我不太懂C++)

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

内存映射:

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

如果你现在自由a了,你中间有一个洞。它没有被释放,因为它不能被释放。如果你 free 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

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

于 2012-08-29T14:04:42.480 回答
1

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

从成功的事实来看drop_caches,您可以推断是内核缓存而不是进程的堆正在填满内存。使用free命令找出实际有多少内存可供应用程序使用,尤其是。-/+ buffers/cache它报告的行。

于 2012-08-29T13:31:14.803 回答
1

调用delete程序会导致内存返回到作为程序运行时一部分的内存管理器。原则上,这可以写成将释放的内存返回给操作系统,但如果这样做我会感到惊讶。而是保留回收的内存以供后续调用new.

请注意,这是您的进程的虚拟内存;在程序执行期间的任何时候,有多少实际驻留在物理内存中取决于整个系统负载并由操作系统处理。

于 2012-08-29T13:55:57.033 回答
0

据我所知,用户对 malloc 和 free(或 new 和 delete)的调用永远不会将不再使用的页面返回给 O/S。相反,它们只记住已释放的内存,因此如果您执行的 malloc/new 的大小可以由先前释放的内存满足,那么它将使用该内存,而不是转到 O/S 并使用 sbrk 来获取更多的记忆。

因此这段代码:

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

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

于 2012-08-29T14:45:14.317 回答