2012-08-13 66 views
3

我用下面的代码的一个问题:QImage和valgrind;存储器泄漏

#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的实现是私有的,所以无法调用它。

有人可能会争辩说,这不是一个真正的内存泄漏,因为每个图像格式只有一个按键,但是imho,干净的方法是在退出之前清除所有内容。

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

+0

你不应该打扰自己这种问题,因为Qt有系统释放所有未使用的内存。你正在寻找问题,他们不存在。 Qt在销毁qimage对象时会释放这些内存。不知道为什么valgrind没有看到。 – Blood 2012-08-13 15:20:25

+0

如果您在任何更大的基于Qt的项目上运行它,Valgrind将在Qt实现中发现数百个可能的内存泄漏。我不知道是否所有这些都是真正的内存泄漏,或者valgrind是否被Qt中大量使用的指针所困惑。但是,如前所述,我不会为此而烦恼。 – scai 2012-08-13 15:57:50

回答

1

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

+0

这就是我感觉到的。这让我想起某种Singleton设计模式(用于加载插件的列表),但是它们对valgrind没有任何问题吗? – xoolive 2012-08-13 19:25:19

+0

所以没有办法手动清理加载的插件列表? – xoolive 2012-08-13 19:25:46

+0

不,但你为什么要?它们旨在持续应用程序的生命周期,并由操作系统清理。 – cmannett85 2012-08-13 20:11:04

-2

为什么不使用QCoreApplication?只有这样QObject GC才会起作用。只有这样才能正确清理。 Qt内部是围绕太多的指针进行构建的,这些指针由主事件循环管理,并且完全混乱且具有破坏性。

+1

'QObject'子对象的销毁与'QCoreApplication'无关。 – cmannett85 2015-11-17 19:41:56