为啥我的 C++ 程序的内存使用量不断增长?

Posted

技术标签:

【中文标题】为啥我的 C++ 程序的内存使用量不断增长?【英文标题】:Why does my C++ program's memory usage keep growing?为什么我的 C++ 程序的内存使用量不断增长? 【发布时间】:2012-04-27 01:52:18 【问题描述】:

我是 Linux 和 C++ 新手,对我的应用程序的内存使用有疑问。

我的应用程序处理大量实时数据,大约每秒 500 条消息。

我使用 std::map 来管理(即插入和删除)所有消息。例如,

std::map<int, data_struct> m_map;

// when receive a new message, convert the message into a data structure
m_map.insert(std::pair<int, data_struct>(message.id, data));

// when need to erase a message
iter = m_map.find(id);
if (iter != m_map.end()) 
    m.map.erase(iter);

m_map 的大小大致在2500左右,即应用一开始接收到很多新消息,然后逐渐需要擦除消息。大约 10 秒后,收到的新消息数量与需要删除的消息数量大致相同。

我的问题是,大约 20 分钟后,在 Linux System Monitor 中,我注意到我的应用程序使用的内存约为 1GB。而且它的大小似乎每 20 分钟翻一番。这是正常的吗,应用程序真的使用了那么多内存吗?我在这里遗漏了什么吗?

谢谢。

【问题讨论】:

您可能有内存泄漏。要么就是你的应用程序没有跟上你想象的那么好。大多数人可能会为这样的事情使用消息队列(例如RabbitMQ)。 也许你这样做有一些特定的原因,但你可以使用map.erase(id)。有一个版本的erase,它将键作为参数并返回删除的元素数。 data_struct 是什么样子的? 将众多“make_unique”函数之一复制到您的代码中,并使用智能指针。很有可能,这将解决您的问题,以及您从未知道的许多其他问题。 【参考方案1】:

如果您的程序经常分配和取消分配内存块,您会得到fragemtation - 操作系统只能做很多事情来确保您分配的内存块之间没有间隙。但一般情况下,由此产生的内存使用会趋于平稳。

如果您的程序的内存不断增加,则您有内存泄漏 - 或者您忘记了 delete 对象(或者在 C 样式分配的情况下调用 free())或者您正在将您的对象堆积在一个容器中而忘记删除它们。

要查找丢失的delete 呼叫,请使用valgrind!

使用 valgrind 检测内存泄漏就像使用您喜欢的包管理器安装它然后运行一样简单

valgrind my_program

您的程序将运行,完成后,valgrind 将转储非常详细的内存泄漏报告及其来源,包括完整的堆栈跟踪。

valgrind 很棒。

【讨论】:

@michael,感谢您的建议。您能否提供一个链接或示例,说明如何使用 valgrind 查找丢失的删除调用、内存泄漏等。谢谢。【参考方案2】:

map::erase() 调用对象的析构函数,所以你应该在那里处理内存泄漏

也许,如果您可以测量使用的内存增加了多少,以及数据结构的大小,您就会很好地提示问题出在哪里。

您每 20 分钟收到大约 600.000 条消息。如果内存使用量从 1GB 翻倍到 2GB,则每条消息会丢失 1.8kB(1GB / 20 分钟内 600.000 条消息)

【讨论】:

【参考方案3】:

嗯,内存使用量增加不仅仅意味着泄漏。

RSS(驻留大小)是否在增加? 或者 VSZ(虚拟大小)是否增加?

你可以通过运行“ps -aux”找到

我的经验是,如果 RSS 保持不变并且 VSZ 不断增加,那么它肯定是内存泄漏。

如果 RSS 不断增长并且您的 VSZ 在某个时候稳定下来,那么您每次都会触及大量内存并且您正在增加所触及的内存量,在您的代码中发现这一点很困难。

【讨论】:

以上是关于为啥我的 C++ 程序的内存使用量不断增长?的主要内容,如果未能解决你的问题,请参考以下文章

如何修复 ray 不断增长的内存使用量?

Dask Worker 进程内存不断增长

在多线程环境中使用 PyCurl 时程序消耗的内存不断增长

NodeJS 内存增长(内存泄漏)

Sqlite插入数据 内存不断增长怎么解决

Joblib 内存使用量不断增长