QTcpSocket 在工作进程中连续写入。避免内存泄漏的最佳实践

QTcpSocket continuous write in worker process. Best practice to avoid memory leaks

我必须在特定的时间间隔内通过 TCP 套接字向服务器发送一个小数据包。我正在用 Qt 开发。 我的想法是创建继承自 QObject 的 class,将 Socket 写入部分放入这样的 class 中的无限循环中,并将其作为单独的线程执行。
它可以工作,但会泄漏内存....在这一点上我很迷茫。
这是我到目前为止所做的(某种伪代码...):

Task_SendPacket.h

#ifndef TASK_SENDPACKET_H
#define TASK_SENDPACKET_H

#include <QObject>
#include <QTcpSocket>

class Task_SendPacket : public QObject
{
    Q_OBJECT
public:
    explicit Task_SendPacket(QObject *parent = nullptr);

public slots:
    void startTask();

    void _connected();
    void _readReady();
    void _error(QAbstractSocket::SocketError _Error);

signals:

private:

    QTcpSocket *mpSocket;
    char SomeData[100];
};

#endif // TASK_SENDPACKET_H

Task_SendPacket.cpp

#include "Task_SendPacket.h"

#include <QThread>
#include <QDebug>

Task_SendPacket::Task_SendPacket(QObject *parent)
    : QObject(parent)
{

}

void Task_SendPacket::startTask(){

while(true){

        mpSocket = new QTcpSocket(this);

        connect(mpSocket, &QTcpSocket::disconnected, mpSocket, &QTcpSocket::deleteLater);
        connect(mpSocket, &QTcpSocket::connected, this, &Task_SetSelectedCamera::_connected);
        connect(mpSocket, &QTcpSocket::readyRead, this, &Task_SetSelectedCamera::_readReady);
        connect(mpSocket, &QTcpSocket::errorOccurred,this, &Task_SetSelectedCamera::_error);

        mpSocket->connectToHost("192.168.0.1", 50100, QTcpSocket::ReadWrite);

        if(!mpSocket->waitForConnected(Protocol::NetworkTimeout_ms)){

            qWarning() << "SS Packet send - Connection timeout";
        }

        if(!mpSocket->waitForBytesWritten(Protocol::NetworkTimeout_ms)){

            qWarning() << "SS Packet send - write timeout";
            mpSocket->disconnectFromHost();
        }

        if(!mpSocket->waitForReadyRead(Protocol::NetworkTimeout_ms)){

            qWarning() << "SS Packet send - read timeout";
            mpSocket->disconnectFromHost();
        }
    
    QThread::msleep(1000);
}

void Task_SetSelectedCamera::_connected(){
    
    if(mpSocket->write(SomeData, 100) == -1){
        qWarning() << "Write Header error ";
    };
}

void Task_SetSelectedCamera::_readReady(){

    char DataRead[100] = mpSocket->readAll();

    /* Do stuff with DataRead...*/

    mpSocket->disconnectFromHost();

}

void Task_SetSelectedCamera::_error(QAbstractSocket::SocketError _Error){

    qWarning() << _Error;

}
}

main.cpp

/* Start Task SetSelectedCamera */
    QThread *ServiceThread1 = new QThread();
    Task_SendPacket *oTaskSendPacket = new Task_SendPacket();
    oTaskSendPacket->moveToThread(ServiceThread1);

    QObject::connect(ServiceThread1, &QThread::finished, oTaskSendPacket, &QObject::deleteLater);
    QObject::connect(ServiceThread1, &QThread::started, oTaskSendPacket, &Task_SendPacket::startTask);
    ServiceThread1->start();
    qInfo() << "Task SendPacket started";

如果我让应用程序 运行 运行几天,它会增加内存并崩溃。
这是创建新 QTcpSocket、连接它并发送数据的正确方法吗?

萨克斯

编辑
我已经编辑了原来的 post 因为我没有关注正确的点。在我的想法中, new QTcpSocket(...) 必须在 while 循环的每次迭代中 运行 因为我希望 mpSocket 每次断开连接时都被标记为删除。
在第二个实验中(在下面报告)我试图在 while 循环之前移动套接字部分......它仍然有效。

mpSocket = new QTcpSocket(this);

connect(mpSocket, &QTcpSocket::disconnected, mpSocket, &QTcpSocket::deleteLater);
connect(mpSocket, &QTcpSocket::connected, this, &Task_SetSelectedCamera::_connected);
connect(mpSocket, &QTcpSocket::readyRead, this, &Task_SetSelectedCamera::_readReady);
connect(mpSocket, &QTcpSocket::errorOccurred,this, &Task_SetSelectedCamera::_error);

while(true){ 

    mpSocket->connectToHost("192.168.0.1", 50100, QTcpSocket::ReadWrite);

    if(!mpSocket->waitForConnected(Protocol::NetworkTimeout_ms)){

        qWarning() << "SS Packet send - Connection timeout";
    }

    if(!mpSocket->waitForBytesWritten(Protocol::NetworkTimeout_ms)){

        qWarning() << "SS Packet send - write timeout";
        mpSocket->disconnectFromHost();
    }

    if(!mpSocket->waitForReadyRead(Protocol::NetworkTimeout_ms)){

        qWarning() << "SS Packet send - read timeout";
        mpSocket->disconnectFromHost();
    }

    QThread::msleep(1000);
}

所以现在的问题是:

  1. 每次迭代都创建一个新的 QTcpSocket 是否正确?
  2. 为什么断开连接后套接字仍然有效(因为我这样做了 收到断开连接...我跟踪了)

真丢脸!
我在很多方面都错了,但请原谅我,我年轻又花哨。

我想 post 在这里谈谈我犯过的错误,希望它能帮助其他人,因为我认为我已经得到了这个错误的解决方案,这是受我以前使用 RTOS 编程的性经验的影响。

首发
永远不要在 QThread 或 QObject 中放置无限 while 循环,即 moveToThread(...) 到 QThread。这是因为 while 循环将使 QEventLoop 与 运行 保持一致。一切都会卡在里面

while(true){

...

}

和none应用程序的生命周期(包括信号和槽)将继续!

然后 - Signal/Slot卡住
如果没有

...
if(!mpSocket->waitForBytesWritten(Protocol::NetworkTimeout_ms)){

    qWarning() << "SS Packet send - write timeout";
    mpSocket->disconnectFromHost();
}

if(!mpSocket->waitForReadyRead(Protocol::NetworkTimeout_ms)){

    qWarning() << "SS Packet send - read timeout";
    mpSocket->disconnectFromHost();
}
...

没有ReadyRead信号,没有BytesWritten信号等等。这是(显然......现在)因为这些函数正在阻塞并且因为我的无限循环正在阻塞 signal/slot 逻辑所以没有其他方法可以让我的 QTcpSocket 工作。如果应用程序生命周期正常运行,则信号和插槽会正常运行,否则......它们不会。

最后 - deleteAater() 不工作
我无法理解的最后一件事是为什么,把我的

mpSocket = new QTcpSocket(this);

在 while 循环之前(应该在每次迭代时删除套接字,套接字仍然可以工作。
这也是因为如果 QEventLoop 不工作,套接字的 deleteLater() 将不工作......顺便说一句,这也是(我认为)我的应用程序泄漏内存的原因!

现在我已经用 QTimer 逻辑重新实现并且它工作正常。


我认为我被骗的原因是因为来自 RTOS 的基本思想是在每个线程中都有一个初始化部分和一个循环部分。这就是我寻找无限循环的原因...

仍然怀疑我如何在没有以下条件的情况下在 QThread 中进行无限循环:

  1. 打乱应用程序逻辑
  2. 使用 QTimer

谢谢