Почему чтение изображений в другом потоке с помощью QtConcurrent вызывает утечку памяти? - PullRequest
0 голосов
/ 20 января 2019

Я пытаюсь реализовать предварительную загрузку изображений рядом с тем, что запрашивается в другом потоке, и сохраняю их в QPixmapCache, но даже если я не сохраняю изображения, кажется, что есть утечка памяти.

Valgrind не показывает утечек памяти при использовании этого метода, но объем памяти программы превысит 500 МБ, даже если я удалю код, добавляющий изображения в QPixmapCache.Если он добавлен в QPixmapCache, использование памяти превышает гигабайт.

Я проверил, чтобы убедиться, что FutureWatcher удалялся правильно, и, действительно, при удаленном вызове deleteLater память просачивается намного быстрееи Valgrind обнаруживает утечку.

QFutureWatcher<QVImageAndFileInfo> *cacheFutureWatcher = new QFutureWatcher<QVImageAndFileInfo>();
connect(cacheFutureWatcher, &QFutureWatcher<QVImageAndFileInfo>::finished, [cacheFutureWatcher, this](){
    addToCache(cacheFutureWatcher->result());
    cacheFutureWatcher->deleteLater();
});
cacheFutureWatcher->setFuture(QtConcurrent::run(this, &QVImageCore::readFile, filePath));

И вот что запускается в readFile:

QVImageCore::QVImageAndFileInfo QVImageCore::readFile(const QString fileName)
{
    QVImageAndFileInfo combinedInfo;

    QImageReader newImageReader;
    newImageReader.setDecideFormatFromContent(true);
    newImageReader.setAutoTransform(true);

    newImageReader.setFileName(fileName);
    const QImage readImage = newImageReader.read();

    combinedInfo.readFileInfo = QFileInfo(fileName);
    if (readImage.isNull())
    {
        emit readError(QString::number(newImageReader.error()) + ": " + newImageReader.errorString(), fileName);
        currentFileDetails = lastFileDetails;
        emit fileInfoUpdated();
        return combinedInfo;
    }

    combinedInfo.readImage = readImage;
    return combinedInfo;
}

Я ожидаю, что использование памяти не увеличится так сильно после чтения изображений в другоми уменьшаться со временем.

Если потребуется дополнительная информация, я с радостью предоставлю.Я был озадачен этим неделями.

Ответы [ 2 ]

0 голосов
/ 02 февраля 2019

Я отправил отчет об ошибке и получил некоторое представление от разработчиков Qt здесь: https://bugreports.qt.io/browse/QTBUG-73413

0 голосов
/ 21 января 2019

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

Я предполагаю, что вы видите кеши изображений, которые хранятся дольше, чем нужно. Чтобы убедиться, что мы точно знаем, откуда возникла проблема, попробуйте выполнить следующие действия:

  1. Замените QVImageCore::readFile пустым методом, который ничего не делает, но возвращает простое целое число (и, возможно, используйте QThread::sleep для симуляции работы)
  2. Прямой вызов оригинала QVImageCore::readFile без использования QtConcurrent::run
  3. Оставьте будущего наблюдателя и вместо этого дождитесь будущего, возвращенного QtConcurrent::run (блокировка)
  4. То же, что 3, но не ждите результата

В зависимости от результатов мы можем выяснить, откуда именно возникла ошибка. Ваш последний комментарий однако смущает меня. Не должно быть никакой разницы в поведении между выделением стека и выделением кучи при удалении вручную.

Если ничего не помогает, вы всегда можете попробовать запустить приложение с помощью анализатора памяти, чтобы выяснить, откуда выделяется эта память и кто ее удаляет.

...