Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

QModbusTcpClient 内存泄漏



  • 大家好:

    我在使用 QModbusTcpClient 用以太网 modbus tcp 读数据时能正常。但发现不停增加内存使用。
    只要有数据接收到就会几K内存增加。半天不到程序使用内存120M+ 了。启动时是8M。
    而我用QModbusRtuSerialMaster 用RS485 一切很正常,内存不会增加!

    #ifndef CMODBUS_H
    #define CMODBUS_H
    
    #include <QModbusTcpClient>
    #include <CSerialPortConfig.h>
    #include <QModbusRtuSerialMaster>
    
    class CModBus : public CSerialPortConfig
    {
        Q_OBJECT
    public:
        explicit CModBus(const QString &capstr);
        ~CModBus();
    
        void portOpen();
        void portClose();
        bool portIsOpen();
    
        void read(const QModbusDataUnit &mdu, const int &address);
        void write(const QModbusDataUnit &mdu, const int &address);
    
    signals:
        void linkState(const int &address, const bool &st);
        void dataReady(const int &address, const QModbusDataUnit &mdu);
    
    private:
        void readReady();
        void writeFinished();
        void newSetttings(const Settings &ns);
        void errorOccurred(const QModbusDevice::Error &error);
    
        int m_lastAddress = 0;
        QModbusClient *m_device = nullptr;
    };
    
    #endif // CMODBUS_H
    
    
    #include "CModBus.h"
    
    CModBus::CModBus(const QString &capstr) : CSerialPortConfig(capstr)
    {    
        newSetttings(curSettings());
        connect(this, &CSerialPortConfig::sigNewSetttings, this, &CModBus::newSetttings);
        connect(m_device, &QModbusClient::errorOccurred, this, &CModBus::errorOccurred);
        m_device->connectDevice();
    
        if(m_device->state() != QModbusDevice::ConnectedState)
        {
            errorAppend(capstr + " : " + portName() + tr(" : port error!"));
        }
    }
    
    CModBus::~CModBus()
    {
    
    }
    
    void CModBus::newSetttings(const Settings &ns)
    {
        bool isopen = false;
    
        if(m_device != nullptr)
        {
            isopen = (m_device->state() == QModbusDevice::ConnectedState);
            delete m_device;
            m_device = nullptr;
        }
    
        if(ns.tcpEnable)
        {
            m_device = new QModbusTcpClient(this);
            const QUrl url = QUrl::fromUserInput(ns.tcpHost);
            m_device->setConnectionParameter(QModbusDevice::NetworkPortParameter, url.port());
            m_device->setConnectionParameter(QModbusDevice::NetworkAddressParameter, url.host());
        }
        else
        {
            m_device = new QModbusRtuSerialMaster(this);
            m_device->setConnectionParameter(QModbusDevice::SerialPortNameParameter, ns.portName);
            m_device->setConnectionParameter(QModbusDevice::SerialParityParameter, ns.parity);
            m_device->setConnectionParameter(QModbusDevice::SerialBaudRateParameter, ns.baud);
            m_device->setConnectionParameter(QModbusDevice::SerialDataBitsParameter, ns.dataBits);
            m_device->setConnectionParameter(QModbusDevice::SerialStopBitsParameter, ns.stopBits);
        }
    
        m_device->setTimeout(ns.responseTime);
        m_device->setNumberOfRetries(ns.numberOfRetries);
    
        if(isopen)
        {
            m_device->connectDevice();
        }
    
    }
    
    void CModBus::read(const QModbusDataUnit &mdu, const int &address)
    {
        if((!m_device) || (m_device->state() != QModbusDevice::ConnectedState))
        {
            emit linkState(address, false);
            return;
        }
    
        QModbusReply *reply = m_device->sendReadRequest(mdu, address);
    
        if(reply)
        {
            m_lastAddress = address;
    
            if(!reply->isFinished())
            {
                connect(reply, &QModbusReply::finished, this, &CModBus::readReady);
            }
            else
            {
                emit linkState(address, false);
                delete reply;
            }
        }
        else
        {
            emit linkState(address, false);
        }
    }
    
    void CModBus::write(const QModbusDataUnit &mdu, const int &address)
    {
        if((!m_device) || (m_device->state() != QModbusDevice::ConnectedState))
        {
            emit linkState(address, false);
            return;
        }
    
        QModbusReply *reply = m_device->sendWriteRequest(mdu, address);
    
        if(reply)
        {
            m_lastAddress = address;
    
            if(!reply->isFinished())
            {
                connect(reply, &QModbusReply::finished, this, &CModBus::writeFinished);
            }
            else
            {
                emit linkState(address, false);
                delete reply;
            }
        }
        else
        {
            emit linkState(address, false);
        }
    }
    
    void CModBus::readReady()
    {
        QModbusReply *reply = qobject_cast<QModbusReply *>(sender());
    
        if(!reply)
        {
            emit linkState(m_lastAddress, false);
            return;
        }
    
        const int address = reply->serverAddress();
        const QModbusDataUnit mdu = reply->result();
    
        if(reply->error() == QModbusDevice::NoError)
        {
            emit dataReady(address, mdu);
            emit linkState(address, true);
        }
        else
        {
            emit linkState(m_lastAddress, false);
        }
    
        reply->deleteLater();
    }
    
    void CModBus::writeFinished()
    {
        auto *reply = qobject_cast<QModbusReply *>(sender());
    
        if(!reply)
        {
            emit linkState(m_lastAddress, false);
            return;
        }
    
        if(reply->error() == QModbusDevice::NoError)
        {
            emit linkState(reply->serverAddress(), true);
        }
        else
        {
            emit linkState(m_lastAddress, false);
        }
    
        reply->deleteLater();
    }
    
    void CModBus::errorOccurred(const QModbusDevice::Error &error)
    {
        Q_UNUSED(error)
        emit linkState(m_lastAddress, false);
    }
    
    void CModBus::portOpen()
    {
        m_device->connectDevice();
    }
    
    void CModBus::portClose()
    {
        m_device->disconnectDevice();
    }
    
    bool CModBus::portIsOpen()
    {
        return (m_device->state() == QModbusDevice::ConnectedState);
    }
    
    
    
    
    

Log in to reply