Утечка памяти в QTcpSocket

У меня есть клиент-серверное приложение, использующее QTcpServer и QTcpSockets, и у меня, похоже, большие утечки памяти. Мне интересно, заключается ли проблема в том, что я использую сокеты Qt, потому что я только что настроил простое тестовое приложение, и после отправки 250 000 000 сообщений в цикле мой клиент увеличивается до 75 мегабайт. Кажется, что если у меня есть несколько миллионов сообщений, я вижу, что мой клиент использует более 300 МБ памяти.

Мне это не кажется правильным, так как я продолжаю посылать сообщения, память просто продолжает расти!

Поэтому я должен ожидать, что мое приложение будет постоянно расти в памяти, учитывая следующий код на подключенном сокете. Если этот сокет оставить открытым, я собираюсь быстро исчерпать память. Я что-то пропустил?

if (socket && socket->isOpen())
{
for(int i = 0; i < 25000000; ++i) {
QString str = "test";
socket->write(str.toStdString().c_str());
}
}

1

Решение

Это ожидается, потому что вы потенциально буферизуете большой объем данных. Это асинхронный API из-за цикла событий Qt, поэтому вам следует дождаться записи, когда программа будет готова к этому.

Вы можете использовать void QIODevice::bytesWritten(qint64 bytes) [signal] сигнал продолжить запись. Если вы используете асинхронный API таким образом, вы избежите большого потребления памяти.

1

Другие решения

Розетка с внутренним буфером QIODeviceи все, что вы записали в него, буферизуется до тех пор, пока сетевой стек не сможет его реально отправить. То, что вы видите, — ожидаемое поведение. write() является не операция блокировки, и в любом случае вы должны никогда никогда блокируйте операции в своем потоке GUI, если только вы не думаете, что пользователям действительно нравятся приложения с мертвым пользовательским интерфейсом.

Возможно, вы хотите поместить свои записи в слот, который будет информирован о прогрессе сокета? Розетки все QIODevice, Ищите там полезные сигналы, bytesWritten() например. Обычно откладывают написание, если значение не возвращается bytesToWrite() ниже установленного порога. Ваш слот для письма может начаться так:

// more than 2 pages worth of stuff still to send, we abstain
if (socket->bytesToWrite() > 1<<13) return;

Nitpick: The toStdString() полностью изящен. Вы должны использовать:

socket->write(str.toUtf8().constData());

Не берите в голову, что для такого тестирования вы можете просто создать массив байтов без использования строки:

const QByteArray testData(1000, ' '); // a 1000 spaces
for (int i = 0; i < 100000; ++i) socket->write(testData);
0

По вопросам рекламы [email protected]