c++ - 为什么使用 QtConcurrent 在另一个线程中读取图像似乎会导致内存泄漏?

标签 c++ multithreading qt memory memory-leaks

我正在尝试实现预加载与另一个线程中请求的图像相邻的图像,并将它们存储在 QPixmapCache 中,但即使我不存储图像,似乎也存在内存泄漏。

Valgrind 显示使用此方法没有内存泄漏,但程序的内存将增加到超过 500MB,即使我删除了将图像添加到 QPixmapCache 的代码。如果将其添加到 QPixmapCache,内存使用量将超过 1 GB。

我进行了测试以确保 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;
}

我希望在另一个线程中读取图像后内存使用量不会急剧增加,而是会随着时间的推移而减少。

如果需要更多信息,我很乐意提供。几个星期以来我一直被这个问题困扰着。

最佳答案

Qt 对许多事情使用内部缓存来加速某些操作,尤其是图像。此外,Qt 在调用 QtConcurrent::run 时会在内部生成线程,并让它们存活一段时间。一段时间后内存确实会自行清理这一事实有力地证明了这与内部缓存有关。

我的猜测是您看到的是保存时间超过所需时间的图像缓存。为确保我们确切知道问题出在哪里,请尝试以下操作:

  1. QVImageCore::readFile 替换为一个空方法,该方法只返回一个简单的整数(并且可能使用 QThread::sleep 来模拟工作)
  2. 不使用QtConcurrent::run直接调用原来的QVImageCore::readFile
  3. 忽略 future 的观察者,而是等待 QtConcurrent::run 返回的 future (阻塞)
  4. 同3,但不要等待结果

根据结果,我们或许能够找出错误的确切来源。然而,你最后的评论让我感到困惑。堆栈分配和手动删除的堆分配之间的行为应该没有区别。

如果没有任何帮助,您始终可以尝试使用内存分析器运行您的应用程序,以找出内存是从哪里分配的以及谁删除了它。

关于c++ - 为什么使用 QtConcurrent 在另一个线程中读取图像似乎会导致内存泄漏?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54280263/

相关文章:

c++ - 真的需要在 .h 和 .cpp 文件中分离 C++ 结构吗?

c++ - 用于返回集合的所有子集的适当数据结构

java - java中如何查找当前拥有锁的线程

qt - QGraphicSscene 在 QGraphicsItem 上绘制移动

java - 找不到 libQt5AndroidExtras.so

c++ - 我想使用 Qxt 的跨度 slider 而无需安装它。这可能吗?

c++ - 如何在我的软件中配置中文支持?

c# - SWIG:将枚举包装到 C#

c - 可靠地将相同的数据广播到 C 中的多个套接字

java - java中如何使用线程?