内存泄漏,在 OOM 时不会崩溃,也不会显示在地块/瓦尔格林德



我有一个内部c++应用程序,它将无限增长——如此之多,以至于我们不得不实现逻辑,一旦RSS达到某个峰值大小(2.0G),实际上就会杀死它,只是为了保持某种表面上的秩序。然而,这显示了一些奇怪的行为。

首先,我通过Valgrind w/memcheck运行应用程序,并在这里和那里修复了一些随机内存泄漏。然而,这些内存泄漏的范围是以10兆字节为单位测量的。这是有道理的,因为它可能没有实际的内存泄漏——它可能只是应用程序端内存管理不良。

接下来,我使用Valgrind w/massif来检查内存的去向,这就是它变得奇怪的地方。峰值快照为161M——远不及我们使用RSS字段看到的1.9G+峰值。最大的消耗是我所期望的——在std::string中——但这并不异常。

最后,这是最令人费解的——在我们意识到这个内存泄漏之前,我实际上是在AWS上测试这个服务,只是为了好玩,在一台CC2.8XL机器上设置了一个很高的数字,44个工人。这是60.5G的内存,而且没有交换空间。快进一个月:我去看主机——看哪,它的RAM已经满了——但是!进程仍然运行良好,只是停留在内存使用的不同阶段——从800M到1.9G几乎均匀分布。每隔一段时间,dmesg打印出一个关于无法分配内存的Xen错误,但除此之外,进程永远不会死亡,并继续积极地处理(即,它们没有"卡住")。

我在这里错过了什么吗?它基本上起作用了,但我怎么也不知道为什么。关于下一步该找什么,有什么好的建议吗?有什么工具可以帮我弄明白吗?

请注意,valgrind memcheck仅在您"放弃"内存时才会发现。while(1) vec.push_back(n++);将填充所有可用内存,但不报告任何泄漏。通过事物的声音,你在某个地方收集占据大量空间的弦。我也做过一些代码,这些代码使用了大量内存,但并没有真正泄漏内存(valgrind很高兴它在各个地方都没有泄漏!)。有时,您可以通过简单地在内存分配中添加一些标记来跟踪它,以指示您将内存分配到何处。

std::函数中,通常有一个Allocator参数。如果您实现了几个不同的内存池,您可能会发现分配内存的位置。

我也看到过这样的情况,我认为进程有内存碎片,所以堆中有很多小的空闲空间——这可能发生在,例如,你通过增加字符串的大小来创建很多字符串。

如果是碎片问题,使用——pages-as-heap=yes选项运行valgrind massif可能会确认它是否是碎片

最新更新