在 Qt5.3(mingw32) 中删除 QQuickView 的内存管理问题

Posted

技术标签:

【中文标题】在 Qt5.3(mingw32) 中删除 QQuickView 的内存管理问题【英文标题】:Memory management issue with deleting QQuickView in Qt5.3(mingw32) 【发布时间】:2014-11-29 11:49:37 【问题描述】:

我们正在使用 Qt/Qml 开发一个应用程序(Qml 嵌入在 QWidget 中)。删除包含 QQuickView(嵌入式)的 QWidget 时,不会完全释放分配的内存。

通过向应用程序添加 QWidget,将分配大约 30MB 的内存,但当小部件删除时,只会释放大约 20MB 的内存。

在QWidget的析构函数中,我已经删除了QQuickView实例,没有其他大对象了。

另外,我很确定 QQuickView 没有正确释放内存。

如何释放 QQuickView 分配的全部内存?

注意:代码非常大(160000 行),因此我不能放示例代码。

提前谢谢...

【问题讨论】:

您是如何衡量在添加 QWidget 时分配了 30MB 而仅释放 20MB 的?。 如果您的程序具有基派生类,请确保将基类析构函数声明为虚拟。这确保了与该特定对象相关的所有类都可以适当地释放资源。 @MantoshKumar 通过在“Windows 任务管理器”中检查。 这不是那么可靠,重要的是不直接从程序堆内存映射。它基本上讲述了私有字节的总使用量,其增加和减少取决于许多因素。我建议阅读此链接以了解有关此内容的完整信息:***.com/questions/1984186/… @Mosi - 创建和销毁小部件 10 次,看看你是否有 100 mb 的“泄漏”。 【参考方案1】:

我编写了一个快速测试来确定在创建和删除QQUickWidget 时是否存在实际泄漏:

class Widget : public QWidget 
    Q_OBJECT
public:
    Widget(QWidget *parent = 0) : QWidget(parent) 
        widget = 0;
        count = 0;
        resize(200, 200);
        layout = new QVBoxLayout(this);
        setLayout(layout);
        QTimer * t = new QTimer(this);
        t->setInterval(200);
        t->setSingleShot(false);
        t->start();
        connect (t, SIGNAL(timeout()), this, SLOT(toggleQuickView()));
    

public slots:
    void toggleQuickView() 
        if (!widget) 
            widget = new QQuickWidget;
            widget->setSource(QUrl::fromLocalFile("d:\\main.qml"));
            connect(widget, SIGNAL(destroyed()), this, SLOT(echo()));
            layout->addWidget(widget);
         else 
            layout->removeWidget(widget);
            widget->deleteLater();
            widget = 0;
        
    

    void echo() 
        PROCESS_MEMORY_COUNTERS memcount;
        if (!GetProcessMemoryInfo(GetCurrentProcess(), &memcount, sizeof(memcount))) return;
        qDebug() << ++count << "created and destroyed," << memcount.WorkingSetSize / (1024 * 1024) << "MB memory used";
    

private:
    QVBoxLayout * layout;
    QQuickWidget * widget;
    int count;
;

它有一个计时器,可以创建/销毁带有已加载 QML 文件的 QQuickWidget,尽管结果最初会上升,但内存使用情况会及时稳定,这表明 Qt 中不太可能存在内存泄漏代码,如果你确实泄漏了内存,那么问题不在于Qt,而在于你自己的代码。

另外,值得一提的是,任务管理器实际上显示的进程使用的内存少于GetProcessMemoryInfo(),我认为后者是两者的更准确的衡量标准。任务管理器读数也没有显示任何内存泄漏,尽管它的值波动更大。

这是输出:

1 created and destroyed, 41 MB memory used
2 created and destroyed, 44 MB memory used
3 created and destroyed, 44 MB memory used
4 created and destroyed, 48 MB memory used
5 created and destroyed, 48 MB memory used
6 created and destroyed, 48 MB memory used
7 created and destroyed, 48 MB memory used
8 created and destroyed, 48 MB memory used
9 created and destroyed, 48 MB memory used
10 created and destroyed, 48 MB memory used
11 created and destroyed, 52 MB memory used
12 created and destroyed, 52 MB memory used
13 created and destroyed, 52 MB memory used
14 created and destroyed, 52 MB memory used
15 created and destroyed, 52 MB memory used
16 created and destroyed, 52 MB memory used
17 created and destroyed, 52 MB memory used
18 created and destroyed, 52 MB memory used
19 created and destroyed, 52 MB memory used
20 created and destroyed, 52 MB memory used
21 created and destroyed, 53 MB memory used
...
50 created and destroyed, 53 MB memory used
...
100 created and destroyed, 53 MB memory used
...
200 created and destroyed, 53 MB memory used
...
500 created and destroyed, 53 MB memory used

【讨论】:

以上是关于在 Qt5.3(mingw32) 中删除 QQuickView 的内存管理问题的主要内容,如果未能解决你的问题,请参考以下文章

qt creator 使用Ui文件的问题

Qt5构建出错问题解决办法

QT5程序发布dll依赖

tr -d 或 sed -e 's/\r//g' 无法从 MINGW32 中的文件中删除 CRLF

Qt 5.3.1 应用程序错误:无法找到或加载 Qt 平台插件“windows”

openal-1.13 静态编译(mingw32)