Memory management issue with deleting QQuickView in Qt5.3(mingw32)
Asked Answered
S

1

2

We are developing an application with Qt/Qml (Qml is embedded in the QWidget). When deleting a QWidget that contains a QQuickView (embedded), the allocated memory won't be freed entirely.

By adding a QWidget to application, about 30MB of memory will be allocated but when the widget deletes, only about 20MB of memory will be freed.

In the destructor of QWidget, I have deleted the QQuickView instance and there are no other big objects.

Also, I am pretty sure that the QQuickView doesn't release memory properly.

How can I free entire memory allocated by QQuickView?

NOTE: The code is really big (160000 Lines), therefore I can't put sample code.

Thanks in advance...

Stephie answered 29/11, 2014 at 11:49 Comment(8)
How did you measure that while adding QWidget 30MB gets allocated and while freeing only 20MB?.Trod
Make sure to declare your base classes destructor to be virtual if your program has base-derived class. This ensures the proper free of resources by all classes related to that particular object.Trod
@MantoshKumar By checking it in "Windows Task Manager".Stephie
That is not so reliable and importantly does not directly maps from program heap memory. Its basically tells about total usage of private bytes which gets increased and decreased depends on many factor. I would suggest to read this link to get the complete idea about this: #1984686Trod
@Stephie - create and destroy the widget 10 times and see if you have 100 mb "leaked".Beam
@ddriver - Yeah, I did it and I've got 100mb leaked!!!!Stephie
Does a simple QWidget containing a simple QQuickView leak too?Merrie
Task Manager is not a reliable measurement of memory.Cinerarium
B
5

I've written a quick test to determine if there is an actual leak in the creation and deletion of a 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;
};

It has a timer that creates/destroys a QQuickWidget with a loaded QML file inside, and although the results initially ramp up, the memory usage stabilizes in time, indicating it is not likely there was a memory leak in the Qt code, and that if you indeed leak memory, the fault does not lie in Qt but in your own code.

Also, it is worth mentioning that the task manager actually showed the process using less memory than GetProcessMemoryInfo(), and I think the latter is the more accurate measure of the two. The task manager reading also didn't indicate any memory leaking although its value fluctuated more.

Here is the output:

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
Beam answered 29/11, 2014 at 15:32 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.