StackView is cause of Memory leak?
-
wrote on 13 Nov 2023, 03:04 last edited by
I'm creating an app using Stackview.
When I monitored the memory usage of the app while switching pages, I found that the memory usage gradually increased.
So, when I created a simple Staciview test program and verified it, I found that the memory usage gradually increased and was not released.I suspect a memory leak. Is there any solution?
I uses Qt 6.5.2.test method on test program:
main page->click button and move to page1->click button and move to page2->back button (pop)->back button (pop)-> main pagemain.cpp
#include <QGuiApplication> #include <QQmlApplicationEngine> int main(int argc, char *argv[]) { QGuiApplication app(argc, argv); QQmlApplicationEngine engine; const QUrl url(u"qrc:/main.qml"_qs); QObject::connect(&engine, &QQmlApplicationEngine::objectCreated, &app, [url](QObject *obj, const QUrl &objUrl) { if (!obj && url == objUrl) QCoreApplication::exit(-1); }, Qt::QueuedConnection); engine.load(url); return app.exec(); }
main.qml
import QtQuick 2.15 import QtQuick.Controls 2.15 import QtQuick.Layouts 1.15 ApplicationWindow { width: 640 height: 480 visible: true title: qsTr("Hello World") Timer{ interval: 100; running: false; repeat: true onTriggered: { } } StackView { id: stackView width:parent.width*0.98 height:parent.height*0.98 anchors.centerIn: parent focus: true initialItem:buttons onCurrentItemChanged: { console.log("stack depth=",stackView.depth) } } ListModel{ id:menuItems ListElement{ _txt:qsTr("1") _url: "Page1.qml" _accent:false _name:"page1" _type:"btn" } ListElement { _txt:qsTr("2") _url:"Page2.qml" _accent:false _name:"page2" _type:"btn" } } Component{ id:buttons GridView{ id:grid cellWidth:parent.width/3 cellHeight:parent.height/3 model:menuItems delegate: Button{ text:_txt //checkable: name==="conveyormode"?true:false onClicked:{ stackView.push(Qt.resolvedUrl(_url),StackView.Immediate) } } } } }
Page1.qml
import QtQuick 2.15 import QtQuick.Controls 2.15 import QtQuick.Layouts 1.15 Page { Rectangle{ width:100;height:100 Button{ id:bk text:"(1) back" onClicked:stackView.pop(StackView.Immediate); } Button{ text:"to 2" onClicked:stackView.push(Qt.resolvedUrl("Page2.qml"),StackView.Immediate) anchors.left: bk.right } } }
Page2.qml
import QtQuick 2.15 import QtQuick.Controls 2.15 import QtQuick.Layouts 1.15 Page { Rectangle{ width:100;height:100 Button{ text:"(2) back" onClicked:stackView.pop(StackView.Immediate); } } }
-
wrote on 15 Nov 2023, 03:51 last edited by ynatynat
I have been tested well my app which modified including gc() excluding Glow{}& Qt5Compat.GraphicalEffects.
As a result, it didn't consume much memory.[Conclusion]
StackView is not a cause of memory leak.--in my app:
Glow{} (Qt5Compat.GraphicalEffects) was the cause of memory leak. So I removed them.
Periodically running gc() is effective to reduce memory consumption if user operate continuously. -
I'm creating an app using Stackview.
When I monitored the memory usage of the app while switching pages, I found that the memory usage gradually increased.
So, when I created a simple Staciview test program and verified it, I found that the memory usage gradually increased and was not released.I suspect a memory leak. Is there any solution?
I uses Qt 6.5.2.test method on test program:
main page->click button and move to page1->click button and move to page2->back button (pop)->back button (pop)-> main pagemain.cpp
#include <QGuiApplication> #include <QQmlApplicationEngine> int main(int argc, char *argv[]) { QGuiApplication app(argc, argv); QQmlApplicationEngine engine; const QUrl url(u"qrc:/main.qml"_qs); QObject::connect(&engine, &QQmlApplicationEngine::objectCreated, &app, [url](QObject *obj, const QUrl &objUrl) { if (!obj && url == objUrl) QCoreApplication::exit(-1); }, Qt::QueuedConnection); engine.load(url); return app.exec(); }
main.qml
import QtQuick 2.15 import QtQuick.Controls 2.15 import QtQuick.Layouts 1.15 ApplicationWindow { width: 640 height: 480 visible: true title: qsTr("Hello World") Timer{ interval: 100; running: false; repeat: true onTriggered: { } } StackView { id: stackView width:parent.width*0.98 height:parent.height*0.98 anchors.centerIn: parent focus: true initialItem:buttons onCurrentItemChanged: { console.log("stack depth=",stackView.depth) } } ListModel{ id:menuItems ListElement{ _txt:qsTr("1") _url: "Page1.qml" _accent:false _name:"page1" _type:"btn" } ListElement { _txt:qsTr("2") _url:"Page2.qml" _accent:false _name:"page2" _type:"btn" } } Component{ id:buttons GridView{ id:grid cellWidth:parent.width/3 cellHeight:parent.height/3 model:menuItems delegate: Button{ text:_txt //checkable: name==="conveyormode"?true:false onClicked:{ stackView.push(Qt.resolvedUrl(_url),StackView.Immediate) } } } } }
Page1.qml
import QtQuick 2.15 import QtQuick.Controls 2.15 import QtQuick.Layouts 1.15 Page { Rectangle{ width:100;height:100 Button{ id:bk text:"(1) back" onClicked:stackView.pop(StackView.Immediate); } Button{ text:"to 2" onClicked:stackView.push(Qt.resolvedUrl("Page2.qml"),StackView.Immediate) anchors.left: bk.right } } }
Page2.qml
import QtQuick 2.15 import QtQuick.Controls 2.15 import QtQuick.Layouts 1.15 Page { Rectangle{ width:100;height:100 Button{ text:"(2) back" onClicked:stackView.pop(StackView.Immediate); } } }
@ynatynat As I wrote here https://forum.qt.io/topic/152053/best-practices-of-handling-multiple-forms?_=1699862117332 I doubt there is a memory leak.
-
@ynatynat As I wrote here https://forum.qt.io/topic/152053/best-practices-of-handling-multiple-forms?_=1699862117332 I doubt there is a memory leak.
wrote on 13 Nov 2023, 08:52 last edited by@jsulm
Thank you for replaying.
You means it's not a memory leak, but memory is increasing due to natural memory management by the OS (not freeing it for reuse), right?
I'm creating an app that will be used in a factory, and I don't have many chances to shut down the app, so I would like to reduce memory consumption as much as possible. How can I achieve this? -
@jsulm
Thank you for replaying.
You means it's not a memory leak, but memory is increasing due to natural memory management by the OS (not freeing it for reuse), right?
I'm creating an app that will be used in a factory, and I don't have many chances to shut down the app, so I would like to reduce memory consumption as much as possible. How can I achieve this?@ynatynat You would need to reserve and release more memory many times to see whether there is really a memory leak. Releasing one window and seeing that the memory is still not released does not automatically mean that there is a memory leak.
-
@jsulm
Thank you for replaying.
You means it's not a memory leak, but memory is increasing due to natural memory management by the OS (not freeing it for reuse), right?
I'm creating an app that will be used in a factory, and I don't have many chances to shut down the app, so I would like to reduce memory consumption as much as possible. How can I achieve this?wrote on 13 Nov 2023, 08:57 last edited by@ynatynat
You do not necessarily have to shut down the app to get the memory back. Once memory is allocated by a process it is "unlikely" to be returned to the OS until the process ends. However, the hope is that the process will re-use that memory after being freed when the process comes to allocate fresh memory.The true test is more like: keep allocating and freeing memory (allowing it to be properly freed by Qt), see whether total memory allocated to the process "settles down" over time rather than keeping growing indefintely.
-
@ynatynat
You do not necessarily have to shut down the app to get the memory back. Once memory is allocated by a process it is "unlikely" to be returned to the OS until the process ends. However, the hope is that the process will re-use that memory after being freed when the process comes to allocate fresh memory.The true test is more like: keep allocating and freeing memory (allowing it to be properly freed by Qt), see whether total memory allocated to the process "settles down" over time rather than keeping growing indefintely.
wrote on 13 Nov 2023, 09:20 last edited by@jsulm
@JonB
Thank you for replying.I tested the app.
test operation: main-move to page1(push(page1))- move to page2(push(page2))-pop()-pop()-main[Result]
Just open:53.6MB
after 1st operation: 55.7MB
after 20th operation:55.9MB
wait one minute and restart operation.
after 40th opereation 55.9MB
after 60th operation 56.2MBIt seems to keep growing.
-
@jsulm
@JonB
Thank you for replying.I tested the app.
test operation: main-move to page1(push(page1))- move to page2(push(page2))-pop()-pop()-main[Result]
Just open:53.6MB
after 1st operation: 55.7MB
after 20th operation:55.9MB
wait one minute and restart operation.
after 40th opereation 55.9MB
after 60th operation 56.2MBIt seems to keep growing.
wrote on 13 Nov 2023, 09:21 last edited by JonB@ynatynat
Run it 100 times.
OIC, you seem to have run it several times, I think. In any case if you are commenting on a difference between 53/55/56MB this is so small it may not be significant.You might also use a tool like valgrind to examine memory allocation. Whether that tool, or another, has issues (e.g. "false positives") with QML code I do not know.
From time to time people post asking/reporting something similar. It is unlikely there are any "leaks" in Qt code, and the behaviour is what it is.
-
-
@ynatynat
Run it 100 times.
OIC, you seem to have run it several times, I think. In any case if you are commenting on a difference between 53/55/56MB this is so small it may not be significant.You might also use a tool like valgrind to examine memory allocation. Whether that tool, or another, has issues (e.g. "false positives") with QML code I do not know.
From time to time people post asking/reporting something similar. It is unlikely there are any "leaks" in Qt code, and the behaviour is what it is.
wrote on 14 Nov 2023, 09:49 last edited by@JonB
Thank you for advice.I understood that a change of about a few MB is not a critical memory leak.
As a result of investigating on my app, rather than test app, I also found that when I press a button that uses Glow{} (Qt5Compat.GraphicalEffects), memory consumption increases continuously. I think it seems a critical leak.I also found it is better to use gc() if there is a possibility of continuous operation. document
That's why, I expect that my program will improve by excluding Glow{}, Qt5Compat.GraphicalEffects and add periodically running gc().
Although I have only been able to do a few tests so far, it appears that memory consumption tends to be less likely to increase when these are included.
-
wrote on 15 Nov 2023, 03:51 last edited by ynatynat
I have been tested well my app which modified including gc() excluding Glow{}& Qt5Compat.GraphicalEffects.
As a result, it didn't consume much memory.[Conclusion]
StackView is not a cause of memory leak.--in my app:
Glow{} (Qt5Compat.GraphicalEffects) was the cause of memory leak. So I removed them.
Periodically running gc() is effective to reduce memory consumption if user operate continuously. -
8/9