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

5

我是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系统监视器中,我注意到我的应用程序使用的内存约为1GB。似乎每20分钟内存大小翻倍。这正常吗?应用程序真的使用那么多内存吗?我错过了什么吗?
谢谢。

6
你可能存在内存泄漏问题,或者你的应用程序没有像你想象的那样跟上进度。大多数人可能会为这种情况使用消息队列(例如 RabbitMQ)。 - Chris Eberle
1
也许你有特定的原因在这样做,但是你可以直接使用 map.erase(id)。有一个版本的 erase 函数可以通过键作为参数来删除元素,并返回被删除的元素数量。 - Corbin
1
数据结构长什么样? - dgnorton
复制其中一个“make_unique”函数到您的代码中,并使用智能指针。很可能,这将解决您的问题,以及许多您从未意识到的其他问题。 - Mooing Duck
3个回答

20
如果您的程序经常分配和释放内存块,就会出现碎片 - 操作系统只能尽力保证您分配的内存块之间没有空隙。但通常情况下,由此产生的内存使用量会趋于稳定。
如果您的程序的内存持续增加,则存在内存泄漏 - 要么您忘记了delete对象(或在C样式分配的情况下调用free()),要么您将对象积累在容器中并忘记删除它们。
要查找缺失的delete调用,请使用valgrind
使用valgrind检测内存泄漏就像使用您喜欢的包管理器安装它,然后运行一样简单。
valgrind my_program

你的程序将会运行,完成后,valgrind会生成一个非常详细的内存泄漏报告,并指出它们的来源,包括完整的堆栈跟踪。
valgrind太棒了。

@michael,感谢您的建议。您能否提供一个使用valgrind查找缺失的delete调用、内存泄漏等问题的链接或示例?谢谢。 - 2607

0

map::erase() 调用了对象的析构函数,所以你应该注意内存泄漏。

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

每 20 分钟会收到约 600,000 条消息。如果内存使用量从 1GB 增加到 2GB,则每条消息大约损失 1.8kB(1GB / 600,000 条消息在 20 分钟内)。


0

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

是 RSS(常驻集大小)在增加吗? 还是 是 VSZ(虚拟集大小)在增加?

您可以通过运行“ps -aux”来找出。

我的经验是,如果 RSS 保持不变而 VSZ 不断增加,则肯定存在内存泄漏。

如果 RSS 不断增长,而您的 VSZ 在某个点稳定下来,则每次都会触及大量内存,并且您正在增加所触及的内存量,要在代码中找到这一点很困难。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接