【问题标题】:QTcpSocket "leaks" memoryQTcpSocket“泄漏”内存
【发布时间】:2014-03-18 13:19:56
【问题描述】:

我需要关于 QTcpSocket 不断增长的记忆的帮助。

当然我发现了类似的问题hereherehere,但不幸的是他们并没有为我解决这个问题。

我写了一个简单的类,封装了QTcpSocket

#include "GWCommunicator.h"

GWCommunicator::GWCommunicator() {
    socket = new QTcpSocket(this);
}

    bool GWCommunicator::send(const char *data, qint64 size) {
        socket->write(data, size);
        return socket->waitForBytesWritten();
    }

    GWCommunicator::~GWCommunicator() {
        delete socket;
    }

    bool GWCommunicator::connectToServer() {
        socket->connectToHost(SERVERIP, 6498, QIODevice::ReadWrite);
        return socket->waitForConnected();
    }

    bool GWCommunicator::disconnectFromServer() {
        socket->disconnectFromHost();
        return socket->waitForDisconnected();
    }

其中socketQTcpSocket*,在头文件中声明为私有字段。

在功能方面,一切都很好。但是这个套接字随着每条消息的发送消耗越来越多的内存。这不是实际的泄漏,而是某种缓冲(与 QIODevice 文档相对应 - QTcpSocket 的注释)。文档还说您可以在打开设备时使用无缓冲模式。但这在 QTcpSocket 中是不可能的:

注意:不能在 QIODevice::Unbuffered 模式下打开 TCP 套接字。

我应该如何避免它?我知道waitForBytesWritten() 应该这样做,但显然没有。

主类如下所示:

#include "GWCommunicator.h"
#include <iostream>

using namespace std;

GWCommunicator *communicator;

int main(/*int argc, char *argv[]*/) {
    communicator = new GWCommunicator();
    communicator->connectToServer();

    string stdstr("Hello world");
    const char* str = stdstr.c_str();
    int count = 0;
    int length = stdstr.size();

    while (count++ < 10000) {
        communicator->send(str, length);
    }

    communicator->disconnectFromServer();
    delete communicator;
    return 0;
}

我的头文件如下。

#include <QObject>
#include <QTcpSocket>

#ifndef GWCOMMUNICATOR_H
#define GWCOMMUNICATOR_H

#define SERVERIP "127.0.0.1"

class GWCommunicator : private QObject {
    Q_OBJECT

public:
    GWCommunicator();
    ~GWCommunicator();
    bool connectToServer();
    bool disconnectFromServer();
    bool send(const char *datam, qint64 size);

private:
    QTcpSocket *socket;

};

#endif  /* GWCOMMUNICATOR_H */

【问题讨论】:

  • 您确定内存泄漏是由QTcpSocket 引起的,而不是由您的代码引起的吗?例如,您可能忘记释放您传递给GWCommunicator::send()const char *data,或类似的东西。要检查QTcpSocket 是否泄漏,请尝试创建一个仅写入套接字的测试程序,然后启动它并读取其输出,看看它是否增加了内存。如果是,请将该测试程序作为 SSCCE 发布。我还注意到您的用户配置文件中的 Java 标记,如果您主要是 Java 程序员,很可能您忘记了释放某些东西。
  • 如果您将父级传递给套接字的构造函数,则不需要delete 它,因为您有双重删除
  • @Kousalik 不过,您是否创建了 SSCCE 并对其进行了测试?如果有,请发布。
  • @Kousalik 啊,那么没有错误,只是错误的错觉。数据确实被缓冲了,但是一旦从套接字中读取它就会从缓冲区中删除。如果您只是“发送”连接另一端从未读取的数据,它当然会累积,等待。如果实际正在读取数据,您能否重现泄漏?试试netcat 这是一个免费工具。
  • 你怎么知道你有内存泄漏?你用的是什么工具?你怎么知道每次通过套接字发送东西时内存消耗都会增加?服务器响应怎么样 - 我在您的代码中看不到任何读数?

标签: c++ qt memory-leaks qtcpsocket


【解决方案1】:

正如@MarekR 所指出的,这种“泄漏”的原因是没有从套接字读取。所以 QTcpSocket 正在缓冲来自服务器的响应。这个分配的内存在从套接字检索传入数据后被释放。

【讨论】:

    【解决方案2】:

    探戈需要两个。你一直写入套接字,而忽略连接的另一端是否从所述套接字读取任何内容。

    您对写入缓冲区的增长负全部责任。您应该检查写入缓冲区的大小(可通过bytesToWrite 获得)并停止写入套接字,如果它已经超过了您感到舒服的某个阈值。

    这绝对没有什么魔力:你,而且只有你,让缓冲区增长。

    bytesToWrite 表示的写入缓冲区的增长表明您的写入速度比另一方读取数据的速度快。这可能有多种原因,例如:

    • 通信渠道慢,

    • 服务器实施不当。

    【讨论】:

    • 服务器是基于 Java 的生产级应用程序,它工作得非常好,并且可以立即接收我发送给它的每条消息。我可以在我的应用程序中等待,但缓冲区保持满。任何进一步的想法?我还仔细检查了 bytesToWrite 及其零。
    猜你喜欢
    • 1970-01-01
    • 2013-10-16
    • 1970-01-01
    • 1970-01-01
    • 2011-10-08
    • 2013-01-20
    • 2011-10-31
    • 2019-08-10
    • 2013-06-24
    相关资源
    最近更新 更多