2012-08-13 109 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