QTcpSocket 内存泄漏

Posted

技术标签:

【中文标题】QTcpSocket 内存泄漏【英文标题】:QTcpSocket memory leaking 【发布时间】:2013-10-03 16:47:39 【问题描述】:

我有一个使用 QTcpServer 和 QTcpSockets 的客户端-服务器应用程序设置,并且似乎有一些巨大的内存泄漏。我想知道问题是否出在我使用 Qt 的套接字上,因为我刚刚设置了一个简单的测试应用程序,并且在循环发送 250,000,000 条消息后,我的客户端上升到 75 兆。似乎如果我有几百万条消息,我会看到我的客户端使用了 300+ MB 的内存。

这对我来说似乎不对,因为我一直在发送消息,内存在不断增加!

因此,鉴于连接套接字上的以下代码,我是否应该期望我的应用程序不断增加内存。如果此套接字保持打开状态,我将很快耗尽内存。我错过了什么吗?

if (socket && socket->isOpen())

    for(int i = 0; i < 25000000; ++i) 
        QString str = "test";
        socket->write(str.toStdString().c_str());
    

【问题讨论】:

您如何初始化/分配您的套接字变量?如果可以,请添加更多代码。 【参考方案1】:

这是意料之中的,因为您可能正在缓冲大量数据。由于 Qt 事件循环,这是一个异步 API,因此您应该在程序准备好时等待写入。

您可以使用void QIODevice::bytesWritten(qint64 bytes) [signal] 信号继续写入。如果你这样使用异步 API,你将避免大量的内存消耗。

【讨论】:

我厌倦了按上述方式编写消息,并同意通过缓冲它会增加内存。我没有补充的是,如果我在事件循环运行(并因此发送消息)的情况下等待一段时间,然后发送(或者更确切地说是缓冲)另一束消息,我看到内存增加了一倍。如果我再次等待然后再发送一些,内存会再次上升。随着消息的发送,缓冲区的大小肯定会减小吗? @user1818822:您是否将您的写入操作作为插槽连接到上述信号?那么,它就不会再发生了。 @user1818822:你知道了吗? 我看到了类似的问题,但有多个连接。我删除了所有的 QTcpSocket,但是,当我同时运行 500 个连接时,每次我拍摄另一个 500 个连接时,内存都会不断增加。我不认为我有内存泄漏,我只是认为这是类的缓冲区管理中的一个错误。 我遇到了同样的问题。通过数百个连接,我看到内存显着增加。您是否以某种方式解决了这个问题?【参考方案2】:

套接字是一个内部缓冲的QIODevice,无论您写入它的任何内容都会被缓冲,直到网络堆栈可以真正将其发送出去。你看到的是预期的行为。 write() 不是阻塞操作,无论如何你应该永远在你的 GUI 线程中执行阻塞操作,除非你认为用户真的喜欢用户界面死机的应用程序。

也许你想把你的文章放在一个插槽中,以便获知套接字的进度?套接字都是QIODevice。在那里寻找有用的信号,例如bytesWritten()。通常推迟写入,除非bytesToWrite() 返回的值低于设定的阈值。你的写作时间可以这样开始:

// more than 2 pages worth of stuff still to send, we abstain
if (socket->bytesToWrite() > 1<<13) return; 

Nitpick:toStdString() 完全没有意义。您应该使用:

socket->write(str.toUtf8().constData());

没关系,对于这样的测试,您可以轻松地创建一个字节数组而不使用字符串:

const QByteArray testData(1000, ' '); // a 1000 spaces
for (int i = 0; i < 100000; ++i) socket->write(testData);

【讨论】:

以上是关于QTcpSocket 内存泄漏的主要内容,如果未能解决你的问题,请参考以下文章

c++ 内存泄漏问题

MFC内存泄漏调试

如何防止java中的内存泄漏

记录一次DialogFragment 内存泄漏

常见的内存泄漏原因及解决方法

Android ValueAnimator --内存泄漏