• 3354阅读
  • 7回复

[提问]关于modbus tcp通讯   QModbusReply  内存累计增加的问题 [复制链接]

上一主题 下一主题
离线飞翔梦幻
 

只看楼主 倒序阅读 楼主  发表于: 2020-12-16
请教论坛大神,这是怎么回事, 我每隔100ms连续不断的往plc存储器里写值,都能够写入,但是内存会不断的累计增加,知道最后程序奔溃...
可能是QModbusReply没完全释放掉。

void CModbusTcpClientWorker::onWriteCoils(int iStartAddr, quint16 uValue, int iServerId)
{

QModbusDataUnit writeUnit(QModbusDataUnit::Coils, iStartAddr, 1);
    writeUnit.setValue(0, uValue);

    bool bWriteResult = false;
    QEventLoop loop;
    QModbusReply* pReply = m_pModbusDevice->sendWriteRequest(writeUnit, iServerId);
    if (NULL != pReply)
    {
        QMetaObject::Connection con = connect(pReply, &QModbusReply::finished, this, [&] {
            if (pReply->error() == QModbusDevice::NoError)
            {
                bWriteResult = true;
            }
            else if (pReply->error() == QModbusDevice::ProtocolError)
            {
                //QString strErrorMsg = QString("Write Coils response error: %1 (Modbus exception: 0x%2)")
                //    .arg(pReply->errorString())
                //    .arg(pReply->rawResult().exceptionCode(), -1, 16);
                //m_Savelog.writeLog(m_Savelog.path, strErrorMsg);
                //ErrorMessage(strErrorMsg);
            }
            else
            {
                //QString strErrorMsg = QString("Write Coils response error: %1 (code: 0x%2)").
                //    arg(pReply->errorString()).
                //    arg(pReply->error(), -1, 16);
                //m_Savelog.writeLog(m_Savelog.path, strErrorMsg);
            }

            loop.quit();
            connect(pReply, &QModbusReply::finished, pReply, &QModbusReply::deleteLater);
            }
        );
        connect(pReply, &QModbusReply::finished, pReply, &QModbusReply::deleteLater);

        QTimer timer;
        timer.setSingleShot(true);
        connect(&timer, SIGNAL(timeout()), &loop, SLOT(quit()));
        timer.start(RW_TIMEOUT_MS);
        loop.exec();

        QObject::disconnect(con);
        //pReply->deleteLater();
    }

    emit writeCoilsResult(bWriteResult, iStartAddr, uValue);
}
离线20091001753

只看该作者 1楼 发表于: 2020-12-17
  1. auto reply = m_pModbusDevice->sendWriteRequest(writeUnit, iServerId);
  2. connect(reply,&QModbusReply::finished,this,[&,reply]{
  3.     switch(reply->error()){
  4.     case QModbusDevice::NoError:break;
  5.     case QModbusDevice::ProtocolError:break;
  6.     default:qDebug()<<reply->errorString();
  7.     }
  8.     reply->deleteLater();
  9. });

(づ ̄ 3 ̄)づ
离线飞翔梦幻

只看该作者 2楼 发表于: 2020-12-17
回 20091001753 的帖子
20091001753:
[code]auto reply = m_pModbusDevice->sendWriteRequest(writeUnit, iServerId);
connect(reply,&QModbusReply::finished,this,[&,reply]{
    switch(reply->error()){
    case QModbusDevice::NoError:break;
    case QModbusDevice::ProtocolError:break;
.......

有一个 异步转同步的过程,在这个地方很容易 stack Flowover  程序奔溃

QTimer timer;
        timer.setSingleShot(true);
        connect(&timer, SIGNAL(timeout()), &loop, SLOT(quit()));
        timer.start(RW_TIMEOUT_MS);
        loop.exec();
在线uidab

只看该作者 3楼 发表于: 2020-12-17
回 飞翔梦幻 的帖子
飞翔梦幻:有一个 异步转同步的过程,在这个地方很容易 stack Flowover  程序奔溃
QTimer timer;
        timer.setSingleShot(true);
....... (2020-12-17 11:42) 

QTimer::singleShot(RW_TIMEOUT_MS,this,[=](){
                 pReply->deleteLater();
                  loop.quit();
                });
也写成lambda形式

有时候为了工作直接获得答案,而我却失去了思考的乐趣!


飘啊飘,何时能安居!
离线飞翔梦幻

只看该作者 4楼 发表于: 2020-12-17
回 uidab 的帖子
uidab:QTimer::singleShot(RW_TIMEOUT_MS,this,[=](){
                 pReply->deleteLater();
               & .. (2020-12-17 13:48) 

这样可以 ,内存还是不断的增加
在线uidab

只看该作者 5楼 发表于: 2020-12-18
回 飞翔梦幻 的帖子
飞翔梦幻:这样可以 ,内存还是不断的增加  (2020-12-17 19:16) 

那你改成智能指针试试
有时候为了工作直接获得答案,而我却失去了思考的乐趣!


飘啊飘,何时能安居!
离线20091001753

只看该作者 6楼 发表于: 2020-12-20
首先,QModbusClient 自带超时设置 setTimeout
所以,你只需要初始化时:
m_pModbusDevice->setTimeout(RW_TIMEOUT_MS);

你代码这么改就好:
  1. void CModbusTcpClientWorker::onWriteCoils(int iStartAddr, quint16 uValue, int iServerId){
  2.     QModbusDataUnit writeUnit(QModbusDataUnit::Coils, iStartAddr, 1);
  3.     writeUnit.setValue(0, uValue);
  4.     auto reply = m_pModbusDevice->sendWriteRequest(writeUnit, iServerId);
  5.     connect(reply,&QModbusReply::finished,this,[&,reply]{
  6.         if(reply->error()){
  7.             emit writeCoilsResult(false, iStartAddr, uValue);
  8.             qDebug()<<reply->errorString();
  9.         }else emit writeCoilsResult(true, iStartAddr, uValue);
  10.         reply->deleteLater();
  11.     });
  12. }


超时也会触发这个 finish 信号,error 是 QModbusDevice::TimeoutError
(づ ̄ 3 ̄)づ
离线neeme

只看该作者 7楼 发表于: 2021-04-16
你好, 我也有这个 modbus tcp 内存累计增加,用rs485串口就没这个问题 。 请问你解决了吗?
开发平台:Ubuntu 16.04 64bit + Qt 5.9.4
运行平台:Ubuntu 16.04 64bit
快速回复
限100 字节
 
上一个 下一个