【问题标题】:QImage and valgrind ; memory leakQImage 和 valgrind ;内存泄漏
【发布时间】:2012-08-14 00:18:15
【问题描述】:

我对以下代码有疑问:

#include <QtGui/QImage>

int main(int argc, char* argv[]) {
  QImage qimage(100, 100, QImage::Format_ARGB32);
  qimage.fill(Qt::white);
  qimage.save("test.png", "PNG", 70);

  return 0;
}

编译如下:

gcc -I/usr/include/qt4 test.cpp -lQtGui

代码生成正确的图像。但是,当我对它进行 valgrind 时:

valgrind --leak-check=full ./a.out

它会产生一系列丢失的块,如下所示:

==5974== 158 (56 direct, 102 indirect) bytes in 1 blocks are definitely lost in loss record 54 of 79
==5974==    at 0x402B9B4: operator new(unsigned int) (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==5974==    by 0x4E4E427: QLibraryPrivate::findOrCreate(QString const&, QString const&) (qlibrary.cpp:437)
==5974==    by 0x4E4E721: QLibrary::setFileNameAndVersion(QString const&, QString const&) (qlibrary.cpp:1110)
==5974==    by 0x56290DF: ???

或者这个:

==5974== 396 (56 direct, 340 indirect) bytes in 1 blocks are definitely lost in loss record 61 of 79
==5974==    at 0x402B9B4: operator new(unsigned int) (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==5974==    by 0x4E4E427: QLibraryPrivate::findOrCreate(QString const&, QString const&) (qlibrary.cpp:437)
==5974==    by 0x4E44FB6: QFactoryLoader::updateDir(QString const&, QSettings&) (qfactoryloader.cpp:145)
==5974==    by 0x56F9E67: ???

我给你完整的日志,你可以在家里执行同样的操作:)

我试图理解,它们似乎位于我在 QImageWriter 的源代码中找到的以下几行:

QFactoryLoader *l = loader();
QStringList keys = l->keys();

在我看来,当您第一次尝试生成 PNG 图像时,它会构建一些内容,每次构建 PNG 图像时都会重复使用这些内容,并且永远不会释放内存。 QFactoryLoader 的析构函数似乎知道如何清理东西,我很想亲自做一个delete l; 但没有办法调用它,因为 QFactoryLoader 是 Qt 实现的私有。

有人可能会说这不是真正的内存泄漏,因为每种图像格式只有一个键,但恕我直言,做事的干净方法是能够在退出前清除所有内容。

所以我的问题是:有没有办法做到这一点?

【问题讨论】:

  • 你不应该为这类问题烦恼,因为 Qt 有系统可以释放所有未使用的内存。您正在寻找不存在的问题。 Qt 将在销毁 qimage 对象时释放此内存。不知道为什么 valgrind 没有看到。
  • 如果你在任何更大的基于 Qt 的项目上运行 Valgrind,它将在 Qt 实现中发现数百个可能的内存泄漏。我不知道所有这些是否都是真正的内存泄漏,或者 valgrind 是否只是因为 Qt 中大量使用指针而感到困惑。但是,如前所述,我不会为此烦恼。

标签: qt valgrind


【解决方案1】:

Qt 的图像 I/O 功能基于插件。当您请求 QImage 加载 png 文件时,PNG 库将作为 QObject 加载 一次,直到程序退出才会卸载 - 这就是 Valgrind 认为的内存泄漏.

【讨论】:

  • 这就是我的感觉。这让我想起了某种单例设计模式(用于加载插件的列表),但它们不会对 valgrind 造成任何问题吗?
  • 那么没有办法手动清理加载的插件列表吗?
  • 不,但您为什么要这样做?它们旨在持续应用程序的生命周期,并由操作系统清理。
  • 我的目的是让 valgrind 在我检查程序的其余部分时保持安静,并且不会被 Qt 噪音打扰。我只是相信一个程序不应该依赖操作系统来清理他的 s***。
  • 我同意,但只是为了简洁起见,这不是内存泄漏,因为消耗的内存不会超过插件运行所需的内存;并且您的操作系统清理了您的堆栈,它是否还可以清理您的堆分配?至于 Valgrind,要使各种输出静音,请使用抑制文件 (valgrind.org/docs/manual/manual-core.html#manual-core.suppress)。
【解决方案2】:

你为什么不使用 QCoreApplication。只有这样 QObject GC 才会起作用。只有这样适当的清理才会起作用。 Qt 内部是围绕着太多的指针构建的,这些指针由主事件循环管理,没有这些指针完全是混乱和破坏性的。

【讨论】:

  • QObject子销毁与QCoreApplication无关。
猜你喜欢
  • 2013-01-12
  • 1970-01-01
  • 1970-01-01
  • 2013-06-24
  • 1970-01-01
  • 2020-03-31
  • 2016-03-15
  • 2014-04-09
  • 1970-01-01
相关资源
最近更新 更多