3

我使用QIcon(Qt 4.8.1 和 MSVC 2008)面临一些内存泄漏。
这发生在简单的QAction(如菜单条目,甚至是由 Qt Designer 自动生成的条目)或容器项(如QTreeWidgetItem)中。
例如:

QTreeWidgetItem *newItem = new QTreeWidgetItem();
newItem->setText(0, "Item");

// This causes a memory leak!
newItem->setIcon(0, QIcon("D:\\Dnl\\QtSandBoxApp\\Resources\\dataset2.png"));

treeWidget->addTopLevelItem(newItem);

经过大量调试后,我发现QIcon内部使用了QImage,它似乎已被正确销毁(参考计数器降至零)。
我可以产生的最简单的例子如下:

#include "stdafx.h"
#include <QtGui/QApplication>
#include <crtdbg.h>

int main(int argc, char *argv[])
{
    _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);

    QApplication a(argc, argv);
    //QPixmapCache::setCacheLimit(0);

    // MEMORY LEAK!
    // Internally uses QImageReader
    QImage image("D:\\Dnl\\QtSandBoxApp\\Resources\\dataset2.png");

    // NO MEMORY LEAK!
    //QImage image(QSize(16, 16), QImage::Format_ARGB32);
    return 0;
}

我错过了什么吗?
这是一个非常烦人的问题,因为它阻止了正确的内存泄漏跟踪(即由应用程序引起,而不是 Qt)。

编辑:这是内存泄漏报告

Detected memory leaks!
Dumping objects ->
{5637} normal block at 0x00A46020, 76 bytes long.
 Data: <d ,g ^      L Bg> 64 D2 2C 67 E8 5E A4 00 00 00 00 00 4C B9 42 67 
{5636} normal block at 0x00A45EE8, 12 bytes long.
 Data: < z   `   z  > 14 7A D3 00 20 60 A4 00 00 7A D3 00 
{5634} normal block at 0x00A46148, 128 bytes long.
 Data: <    6   6   Za  > 01 00 00 00 36 00 00 00 36 00 00 00 5A 61 A4 00 
{5614} normal block at 0x00A45DC8, 76 bytes long.
 Data: <d ,g x      L Bg> 64 D2 2C 67 E8 78 A4 00 00 00 00 00 4C B9 42 67 
{5613} normal block at 0x00A478E8, 12 bytes long.
 Data: <     ]      > A4 96 CA 00 C8 5D A4 00 90 96 CA 00 
{5611} normal block at 0x00A45C48, 128 bytes long.
 Data: <    6   5   Z\  > 01 00 00 00 36 00 00 00 35 00 00 00 5A 5C A4 00 
{5591} normal block at 0x00A477C8, 76 bytes long.
 Data: <d ,g u      L Bg> 64 D2 2C 67 10 75 A4 00 00 00 00 00 4C B9 42 67 
{5590} normal block at 0x00A47510, 12 bytes long.
 Data: <     w      > B8 96 C6 00 C8 77 A4 00 A4 96 C6 00 
{5588} normal block at 0x00A45B88, 128 bytes long.
 Data: <    6   5    [  > 01 00 00 00 36 00 00 00 35 00 00 00 9A 5B A4 00 
{5566} normal block at 0x00A473F0, 76 bytes long.
 Data: <d ,g s      L Bg> 64 D2 2C 67 A8 73 A4 00 00 00 00 00 4C B9 42 67 
{5565} normal block at 0x00A473A8, 12 bytes long.
 Data: <     s      > E0 D7 C3 00 F0 73 A4 00 CC D7 C3 00 
{5563} normal block at 0x00A471E0, 128 bytes long.
 Data: <    6   5    q  > 01 00 00 00 36 00 00 00 35 00 00 00 F2 71 A4 00 
{5543} normal block at 0x00A47008, 76 bytes long.
 Data: <d ,g o      L Bg> 64 D2 2C 67 C0 6F A4 00 00 00 00 00 4C B9 42 67 
{5542} normal block at 0x00A46FC0, 12 bytes long.
 Data: <La   p  8a  > 4C 61 BB 00 08 70 A4 00 38 61 BB 00 
{5540} normal block at 0x00A46DF8, 128 bytes long.
 Data: <    6   6    n  > 01 00 00 00 36 00 00 00 36 00 00 00 0A 6E A4 00 
{5520} normal block at 0x003ED9A8, 76 bytes long.
 Data: <d ,g` >     L Bg> 64 D2 2C 67 60 D9 3E 00 00 00 00 00 4C B9 42 67 
{5519} normal block at 0x003ED960, 12 bytes long.
 Data: <      >     > A4 C6 B4 00 A8 D9 3E 00 90 C6 B4 00 
{5517} normal block at 0x00A46D38, 128 bytes long.
 Data: <    6   5   Jm  > 01 00 00 00 36 00 00 00 35 00 00 00 4A 6D A4 00 
{5496} normal block at 0x003ED8D8, 76 bytes long.
 Data: <d ,g  >     L Bg> 64 D2 2C 67 80 D7 3E 00 00 00 00 00 4C B9 42 67 
{5495} normal block at 0x003ED780, 12 bytes long.
 Data: <<     > (   > 3C CA 00 10 D8 D8 3E 00 28 CA 00 10 
{5491} normal block at 0x00A412A0, 128 bytes long.
 Data: <    6   5       > 01 00 00 00 36 00 00 00 35 00 00 00 B2 12 A4 00 
{5260} normal block at 0x00A48448, 64 bytes long.
 Data: <            Z   > 01 00 00 00 16 00 00 00 13 00 00 00 5A 84 A4 00 
{5233} normal block at 0x00A48380, 56 bytes long.
 Data: <        Ha    Bg> 00 00 CD 00 C0 82 A4 00 48 61 A4 00 04 BA 42 67 
{5231} normal block at 0x00A482C0, 128 bytes long.
 Data: <    6   6       > 01 00 00 00 36 00 00 00 36 00 00 00 D2 82 A4 00 
{4681} normal block at 0x00A48150, 64 bytes long.
 Data: <            b   > 01 00 00 00 16 00 00 00 13 00 00 00 62 81 A4 00 
{4655} normal block at 0x00A47FB8, 56 bytes long.
 Data: <     ~  H\    Bg> 00 00 CA 00 F8 7E A4 00 48 5C A4 00 04 BA 42 67 
{4653} normal block at 0x00A47EF8, 126 bytes long.
 Data: <    5   5       > 01 00 00 00 35 00 00 00 35 00 00 00 0A 7F A4 00 
{4102} normal block at 0x00A47DB8, 64 bytes long.
 Data: <             }  > 01 00 00 00 16 00 00 00 13 00 00 00 CA 7D A4 00 
{4075} normal block at 0x00A47D40, 56 bytes long.
 Data: <     {   [    Bg> 00 00 C6 00 D8 7B A4 00 88 5B A4 00 04 BA 42 67 
{4073} normal block at 0x00A47BD8, 126 bytes long.
 Data: <    5   5    {  > 01 00 00 00 35 00 00 00 35 00 00 00 EA 7B A4 00 
{3522} normal block at 0x00A479F8, 64 bytes long.
 Data: <             z  > 01 00 00 00 16 00 00 00 13 00 00 00 0A 7A A4 00 
{3496} normal block at 0x00A47AA0, 56 bytes long.
 Data: <    8y   q    Bg> 00 00 BD 00 38 79 A4 00 E0 71 A4 00 04 BA 42 67 
{3494} normal block at 0x00A47938, 126 bytes long.
 Data: <    5   5   Jy  > 01 00 00 00 35 00 00 00 35 00 00 00 4A 79 A4 00 
{2943} normal block at 0x00A41220, 64 bytes long.
 Data: <            2   > 01 00 00 00 16 00 00 00 13 00 00 00 32 12 A4 00 
{2917} normal block at 0x00A40418, 56 bytes long.
 Data: <    X    m    Bg> 00 00 B6 00 58 03 A4 00 F8 6D A4 00 04 BA 42 67 
{2915} normal block at 0x00A40358, 128 bytes long.
 Data: <    6   6   j   > 01 00 00 00 36 00 00 00 36 00 00 00 6A 03 A4 00 
{2367} normal block at 0x00A40760, 64 bytes long.
 Data: <            r   > 01 00 00 00 16 00 00 00 13 00 00 00 72 07 A4 00 
{2341} normal block at 0x00A401D0, 56 bytes long.
 Data: <    h   8m    Bg> 00 00 B4 00 68 00 A4 00 38 6D A4 00 04 BA 42 67 
{2339} normal block at 0x00A40068, 126 bytes long.
 Data: <    5   5   z   > 01 00 00 00 35 00 00 00 35 00 00 00 7A 00 A4 00 
{1788} normal block at 0x00A40820, 64 bytes long.
 Data: <            2   > 01 00 00 00 16 00 00 00 13 00 00 00 32 08 A4 00 
{1762} normal block at 0x00A417B0, 56 bytes long.
 Data: <              Bg> 00 00 00 10 B0 18 A4 00 A0 12 A4 00 04 BA 42 67 
{1760} normal block at 0x00A418B0, 126 bytes long.
 Data: <    5   5       > 01 00 00 00 35 00 00 00 35 00 00 00 C2 18 A4 00 
{252} normal block at 0x003E8A08, 40 bytes long.
 Data: <        @B      > 00 00 00 00 CC CD CD CD 40 42 0F 00 00 00 00 00 
{251} normal block at 0x003E8950, 120 bytes long.
 Data: <Lc-g  >     L Bg> 4C 63 2D 67 08 89 3E 00 00 00 00 00 4C B9 42 67 
{250} normal block at 0x003E8908, 8 bytes long.
 Data: < c-gP > > 0C 63 2D 67 50 89 3E 00 
{249} normal block at 0x003E88A0, 40 bytes long.
 Data: <        @B      > 00 00 00 00 CC CD CD CD 40 42 0F 00 00 00 00 00 
{248} normal block at 0x003E8828, 60 bytes long.
 Data: <      >         > 07 00 00 00 08 89 3E 00 80 06 00 00 00 CD CD CD 
Object dump complete.
The program '[2808] QtSandBoxApp.exe: Native' has exited with code 0 (0x0).
4

2 回答 2

4

我解决了这个问题。
在 Qt中使用 CrtDbg 库 API 似乎不是一个好主意。

引自http://winfig.com/?p=154

Qt 在它的 DLL 中分配内存,并且在卸载 DLL 时释放该内存。不幸的是,这是在 Visual Studio 报告所谓的泄漏之后。

就是这样,事实上,当我从磁盘请求QImage时,会在运行时加载以下模块:

'QtSandBoxApp.exe': Loaded 'C:\Libraries\Qt\4.8.1\plugins\imageformats\qgifd4.dll'
'QtSandBoxApp.exe': Loaded 'C:\Libraries\Qt\4.8.1\plugins\imageformats\qicod4.dll'
'QtSandBoxApp.exe': Loaded 'C:\Libraries\Qt\4.8.1\plugins\imageformats\qjpegd4.dll'
'QtSandBoxApp.exe': Loaded 'C:\Libraries\Qt\4.8.1\plugins\imageformats\qmngd4.dll'
'QtSandBoxApp.exe': Loaded 'C:\Libraries\Qt\4.8.1\plugins\imageformats\qsvgd4.dll'
'QtSandBoxApp.exe': Loaded 'C:\Libraries\Qt\4.8.1\bin\QtSvgd4.dll', Symbols loaded.
'QtSandBoxApp.exe': Loaded 'C:\Libraries\Qt\4.8.1\bin\QtXmld4.dll', Symbols loaded.
'QtSandBoxApp.exe': Loaded 'C:\Libraries\Qt\4.8.1\plugins\imageformats\qtgad4.dll'
'QtSandBoxApp.exe': Loaded 'C:\Libraries\Qt\4.8.1\plugins\imageformats\qtiffd4.dll'

Visual Leak Detector正确报告没有内存泄漏。

PS:这个来自 QtCentre 的 wiki 条目具有误导性:P

于 2012-06-11T07:33:55.187 回答
1

避免内存泄漏的另一种方法是,您可以使用带有 QPixmap 的 QIcon 调用,在您的示例中如下所示:

QTreeWidgetItem *newItem = new QTreeWidgetItem();
newItem->setText(0, "Item");

// This causes a memory leak!
newItem->setIcon(0, QIcon(QPixmap("D:\\Dnl\\QtSandBoxApp\\Resources\\dataset2.png")));

treeWidget->addTopLevelItem(newItem);

正如我在我的博客(https://programmersexception.blogspot.com/2019/04/memory-leak-con-qicon-en-qt-594-y.html)中解释的那样,抱歉是西班牙语,有已知的BUG,我希望他们能尽快修复(https://bugreports.qt.io/browse/QTBUG-59621)。

于 2019-04-05T08:03:27.080 回答