У меня есть клиент-серверное приложение, использующее 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());
}
}
Это ожидается, потому что вы потенциально буферизуете большой объем данных. Это асинхронный API из-за цикла событий Qt, поэтому вам следует дождаться записи, когда программа будет готова к этому.
Вы можете использовать void QIODevice::bytesWritten(qint64 bytes) [signal]
сигнал продолжить запись. Если вы используете асинхронный API таким образом, вы избежите большого потребления памяти.
Розетка с внутренним буфером 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);