Добрый день. Столкнулся с проблемой утечки памяти при формировании QImage из полученных через TCP данных. Причем утечку вызывает именно создание экземпляра QImage из fromData, если закомментировать эту строку, то утечки не будет.
Вся схема потока данных такая: сторона отправки читает данные (Метаданные + QImage в виде QByteArray) из файла и отправляет на прием, а сторона приема читает метаданные и картинку и отображает на экране.
Мне кажется, что проблема связанна именно с TCP, т.к. для поиска места где именно течет память я написал приложение видеоплеер. Этот видеоплеер читает данные из файла (код скопировал со стороны отправки), и отображает на экране (код скопировал со стороны приема). То есть видеоплеер объединяет принцип действия отправки и приема, но отправляет данные напрямую, без TCP. И в этом видеоплеере утечка памяти не наблюдается.
Нужно отметить, что сам файл откуда читаются данные немного битый, из-за чего при вызове QImage image = QImage::fromData(imgData, "JPEG");
в лог выводится сообщение:
Corrupt JPEG data: 5 extraneous bytes before marker 0xda
Но, несмотря на этот лог, сама QImage получается корректной и валидной, и без артефактов отображается на экране. В моем видеоплеере тоже отображается этот лог о битых данных, но в видеоплеере память не течёт. Поэтому, мне кажется, что проблема не в данных.
В .h файле на стороне приема у меня объявлен QTcpSocket:
QTcpSocket* m_tcpSocket;
При запуске приложения устанавливаю соединение:
m_tcpSocket->connectToHost(ip, port, flag);
auto connStatus = m_tcpSocket->waitForConnected(1000);
if (connStatus){
connect(m_tcpSocket, &QTcpSocket::readyRead, this, &SmkpStreamChannel::onDataReady);
}
return connStatus;
И затем при получении данных будем попадать в слот:
void SmkpStreamChannel::onDataReady()
{
uint32_t packetStart = 0;
while(packetStart != SmkpProtocol::PACKET_START && m_tcpSocket->bytesAvailable()) {
m_tcpSocket->read(reinterpret_cast<char*>(&packetStart), sizeof(uint32_t));
}
if(packetStart != SmkpProtocol::PACKET_START) {
return;
}
Metadata md;
m_tcpSocket->read(reinterpret_cast<char*>(&md), sizeof(SmkpProtocol::Metadata));
QByteArray imgData(md.videodataSize, '\0');
m_tcpSocket->read(imgData.data(), imgData.size());
QImage image = QImage::fromData(imgData, "JPEG");
//...дальнейшая передача image на экран
}
В моем коде PACKET_START
- это константа преамбула типа uint32_t для сортировки пакетов, а Metadata
- это структура состоящая из набора uint32_t.
Утечку памяти вызывает строка QImage image = QImage::fromData(imgData, "JPEG");
, если убрать эту строку (и соответственно дальнейшее использование image), то утечки памяти не будет. Тут проблема в том, что даже если никак не использовать image, просто объявить и всё, то память всё равно будет течь
Версия Qt 5.12.2, пишу по Astra Linux