Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. QML and Qt Quick
  4. StackView is cause of Memory leak?

StackView is cause of Memory leak?

Scheduled Pinned Locked Moved Solved QML and Qt Quick
9 Posts 3 Posters 1.9k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • Y Offline
    Y Offline
    ynatynat
    wrote on last edited by
    #1

    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 page

    main.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);
        }
    }
    }
    
    
    jsulmJ 1 Reply Last reply
    0
    • Y Offline
      Y Offline
      ynatynat
      wrote on last edited by ynatynat
      #9

      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.

      1 Reply Last reply
      0
      • Y ynatynat

        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 page

        main.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);
            }
        }
        }
        
        
        jsulmJ Offline
        jsulmJ Offline
        jsulm
        Lifetime Qt Champion
        wrote on last edited by
        #2

        @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.

        https://forum.qt.io/topic/113070/qt-code-of-conduct

        Y 1 Reply Last reply
        0
        • jsulmJ jsulm

          @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.

          Y Offline
          Y Offline
          ynatynat
          wrote on last edited by
          #3

          @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?

          jsulmJ JonBJ 2 Replies Last reply
          0
          • Y ynatynat

            @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?

            jsulmJ Offline
            jsulmJ Offline
            jsulm
            Lifetime Qt Champion
            wrote on last edited by
            #4

            @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.

            https://forum.qt.io/topic/113070/qt-code-of-conduct

            1 Reply Last reply
            1
            • Y ynatynat

              @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?

              JonBJ Offline
              JonBJ Offline
              JonB
              wrote on last edited by
              #5

              @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.

              Y 1 Reply Last reply
              0
              • JonBJ JonB

                @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.

                Y Offline
                Y Offline
                ynatynat
                wrote on last edited by
                #6

                @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.2MB

                It seems to keep growing.

                JonBJ 1 Reply Last reply
                0
                • Y ynatynat

                  @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.2MB

                  It seems to keep growing.

                  JonBJ Offline
                  JonBJ Offline
                  JonB
                  wrote on last edited by JonB
                  #7

                  @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.

                  Y 1 Reply Last reply
                  0
                  • JonBJ JonB referenced this topic on
                  • JonBJ 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.

                    Y Offline
                    Y Offline
                    ynatynat
                    wrote on last edited by
                    #8

                    @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.

                    1 Reply Last reply
                    0
                    • Y Offline
                      Y Offline
                      ynatynat
                      wrote on last edited by ynatynat
                      #9

                      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.

                      1 Reply Last reply
                      0
                      • Y ynatynat has marked this topic as solved on

                      • Login

                      • Login or register to search.
                      • First post
                        Last post
                      0
                      • Categories
                      • Recent
                      • Tags
                      • Popular
                      • Users
                      • Groups
                      • Search
                      • Get Qt Extensions
                      • Unsolved