大家好!
我在 Qt 5.8 上通过 QSerialBus
库实现 ModBus 时遇到问题。
问题是 - 当我尝试高速读取离散输入列表时,程序发现内存泄漏 - 大约每秒 300-350Kb。
所以,这里是导致泄漏的函数代码:
void ModBus::queue()
{
if(!_readList.isEmpty())
{
if(!checkState())
{
_readList.clear();
_curPos = DiscInputPos::Full;
queue();
return;
}
QModbusDataUnit readData = QModbusDataUnit(QModbusDataUnit::DiscreteInputs, _readList.first(), 1);
if(auto *reply = _client->sendReadRequest(readData, _serverNum))
{
if(!reply->isFinished())
{
connect(reply, &QModbusReply::errorOccurred, [=] (QModbusDevice::Error e)
{
reply->deleteLater();
if(e == QModbusDevice::TimeoutError)
{
_readList.clear();
_curPos = DiscInputPos::Full;
stop();
start();
queue();
}
});
connect(reply, &QModbusReply::finished, this, [=]
{
if(reply->error() == QModbusDevice::NoError)
{
if(reply->result().valueCount() > 0)
{
_curPos = (DiscInputPos) reply->result().value(0);
if(_curPos == DiscInputPos::Clear)
_readList.removeFirst();
else
_readList.clear();
}
}
else
{
_readList.clear();
_curPos = DiscInputPos::Full;
}
reply->deleteLater();
queue();
});
}
else
delete reply;
}
else
{
delete reply;
_readList.clear();
_curPos = DiscInputPos::Full;
queue();
}
}
else
{
emit sendReadResult(_curPos);
_curPos = DiscInputPos::Full;
}
}
_client
— QModbusTcpClient
bool checkState()
— 除非检查连接状态,否则什么都不做。
最大 _readList
大小为 4。
如果我用 _client->sendReadRequest
注释部分代码 - 一切正常,没有任何泄漏。任何人都可以解释 - 它可以是什么?
提前致谢!
最佳答案
我通过计时器在 0.5 秒 上解决了这个问题(较少也会导致泄漏),它作为检查来自 ModBus
类答案的类的单次滴答滴答作响。仍然有泄漏,但少得多。如果 1 秒 - 没有泄漏。
connect(d, &ModBus::sendReadResult, this, &StatusesWorker::getRead);
void StatusesWorker::getRead(DiscInputPos s)
{
bool cleared = (s == DiscInputPos::Clear);
if(!cleared)
emit badSensors();
else
emit clearSensors();
QTimer::singleShot(500, [=] { checkSensor(id); });
}
}
但我认为这是一个糟糕的解决方案。
UPD。
Qt 社区 solved这样的问题:
connect(reply, &QModbusReply::destroyed, [this] { QTimer::singleShot(60, [this] { queue(); }); });
而且它的工作速度更快,没有泄漏。当然,checkSensor()
现在可以在没有计时器的情况下运行。
关于c++ - QSerialBus 工作中的内存泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42804640/