8

我有一个程序,它接受来自套接字的数据,进行一些质量控制并对其进行其他条件调整,然后将其写入命名管道。我在上面运行了 valgrind 并修复了所有最初存在的内存泄漏。然后,我在一个系统上创建了一个“演示”环境,其中运行了 32 个该程序的实例,每个实例都被提供独特的数据,并且每个都输出到它自己的管道。我们对其进行了测试,一切看起来都很好。然后我尝试通过将数据发送速率提高到荒谬的速率来对其进行压力测试,一开始事情看起来还不错……但是我的程序一直在消耗越来越多的内存,直到我没有剩余资源为止。

我转向 valgrind 并运行完全相同的设置,除了每个程序在 valgrind 中运行时使用泄漏检查 = full。发生了一些奇怪的事情。首先,内存确实泄漏了,但只是到了每个程序都消耗了我 0.9% 的内存的程度(以前最大的内存占用了我 6% 的内存)。随着 valgrind 的运行,程序的 CPU 成本猛增,我现在处于 100% cpu 且平均负载很大,因此可能缺乏可用 CPU 导致程序运行缓慢,以至于泄漏需要很长时间才能显现. 当我尝试停止这些程序时,valgrind 没有显示直接内存泄漏,它显示了一些潜在的内存泄漏,但我检查了它们,我认为它们中的任何一个都不代表真正的内存泄漏;除此之外,当程序消耗超过 100 MB 时,可能的内存泄漏仅显示为几千字节。valgrind 报告的可达(非泄漏)内存也在 KB 范围内,因此 valgrind 似乎认为我的程序正在消耗 Top 所说的它们正在使用的内存的一小部分。

我已经进行了一些其他测试并得到了奇怪的结果。一个程序,即使以我原来的内存泄漏检测速度的三倍运行,似乎从来没有消耗超过 0.9% 的内存,两个程序分别泄漏了 1.9% 和 1.3% 的内存,但没有更多,就好像泄漏的内存量及其泄漏率在某种程度上取决于我的程序一次运行的实例数;这是没有意义的,每个实例都应该 100% 独立于其他实例。

我还发现,如果我运行 32 个实例而只有一个实例在 valgrind 中运行,则 valgrinded 实例(如果我说是的话,那就是一个词!)会泄漏内存,但速度比在 valgrind 之外运行的实例要慢。valgrind 实例仍然会说我没有直接泄漏,并且报告的内存消耗比 Top 显示的要少得多。

对于可能导致此结果的原因,以及为什么 valgrind 拒绝了解内存泄漏,我感到很困惑。我认为它可能是一个外部库,但我并没有真正使用任何外部库;只是基本的 C++ 函数/对象。我还认为可能是写入输出管道的数据快速导致缓冲区无限增长,但是 1)应该有一个这样的缓冲区可以增长的上限,以及 2)一旦内存泄漏,如果我删除数据输入速率为零,内存保持消耗,而不是慢慢下降到合理的数量。

谁能给我一个提示我应该从这里看哪里?我完全不知道为什么内存会这样。

谢谢。

4

3 回答 3

2

您应该首先寻找软泄漏。当一些静态或单例逐渐增加一些缓冲区或容器并将垃圾收集到其中时,就会发生这种情况。从技术上讲,它不是泄漏,但它的影响同样糟糕。

于 2012-08-30T16:27:31.590 回答
2

这听起来像是我最近遇到的一个问题。

如果您的程序接受数据并在内部没有任何限制地对其进行缓冲,那么它的读取和缓冲速度可能比输出数据的速度要快。在这种情况下,内存使用将继续无限制地增加。

您运行的程序实例越多,每个实例的运行速度就越慢,缓冲区增加的速度就越快。

这可能是也可能不是您的问题,但如果没有更多信息,这是我能做的最好的。

于 2012-08-30T23:00:33.127 回答
2

我可以建议您尝试一下 MemoryScape 吗?这个工具在内存泄漏检测方面做得很好。它不是免费的,但考虑到所花费的时间和精力,值得一试。

于 2012-08-30T21:11:03.090 回答