0

main.qml

import QtQuick 2.14
import QtQuick.Window 2.12
import QtQuick.Controls 2.12

Window {
    id: window
    property variant name: []
    property var dialogObject
    Button{
        text: "open window1"
        onClicked: {
            var dialogComponent = Qt.createComponent("qrc:/Window1.qml");
            if (dialogComponent.status == Component.Ready) {
                dialogObject = dialogComponent.createObject(window);
                dialogObject.show()
            }
        }
    }
    Button{
        text: "add array"
        onClicked: {
            for (var i=1; i<10000000; i++){
                name.push(1000000000)
            }
        }
    }
    Button{
        text: "remove array"
        onClicked: delete name[10000000] //do not release!!!!!!!
    }
    Button{
        text: "remove array2"
        onClicked: delete name //do not release!!!!!!!!!!!!!!!!
    }
    Button{
        text: "remove array2"
        onClicked: name = null //do not release!!!!!!!!!!!!!!!
    }
}

Window1.qml

import QtQuick 2.0
import QtQuick.Controls 2.12
import QtQuick.Window 2.12
Window {
    id: window1
    property var name: [] //do not release!!!!!!!!!!!!!!!!!!!!
    Button{
        text: "destroy window1"
            onClicked: {
                window1.destroy()
            }
        }    
    Component.onCompleted: {
        for (var i=1; i<10000000; i++){
            name.push(1000000000)
        }
        console.log("window1 Component.onCompleted:")
    }
    Component.onDestruction: {
        console.log("window1 Component.onDestuction:")
    }
}

Memory of "property var" is not released in Android when deleting a created Qt.createComponent QML component. I monitor the allocation and deletion of memory and see that when the application loaded there were the following indicators:

When I had pressed the button "add array" - Unknown memory value changed and became 262780kb: After I had pressed "remove array" or "remove array2" - nothing changed and Unknown memory the same 262780kb. Memory is not released! If I pressed the button "open window1" the object of Window1 is created and in this time in object Window1 array "name" is had been assigned and memory parameter(Unknown) increase and become 524984kb: enter image description here When I press "destroy window1" button - the window is self destructed by call window1.destroy(), but memory is not changed and remain the same 524984kb. If I press "open window1" button more and more the Unknown memory value is increasing proportionally until the app crashes and is not released! I know that QML has own JS engine and own garbage collector, but when object window1 is has destructed the memory allocated for property var and all included components must released, but it is not happend. The device on which my app worked has small volume of memory and I have a big problem with that. It turns out that the memory is not freed when the object is destroyed. Is there some way to realese memory under property var? How is it to solve this issue with app(Unknown) memory increasing?

5
  • Eventhough you have to signify you no longer need a variable, the variable is still subject to Javascript garbage collector. Generally speaking, it is not meant for you to directly manipulate when Javascript garbage collector fires since that may impact the performance, but, if you insist, you need to call gc(). Such code is generally bad practice. Commented Feb 13, 2023 at 20:47
  • But when I create a new window every time and "property var" variables are created in it, when the window is destroyed, the allocated memory for "property var" is not cleared because they are not in the heap of the process, but most likely belong to the Qt engine JS and his garbage collector, as I see it, does not work from the word at all. Or it is so slow and lazy that it does not have time to detect that the application is no longer using that memory and has freed references to it .. Commented Feb 13, 2023 at 21:26
  • In my application, the same window will often be created, roughly speaking, a million times, and at one fine moment the memory will simply run out, I simulated such a situation and the application simply crashed. Unknown memory grow all time and do not decrease. The only way I see is not to use the "property var" at all in Android. Is it possible to call garbage collector of Qt JS engine? Commented Feb 13, 2023 at 21:26
  • As I indicated, the command is gc() - however, if your app relies on that, then there is something wrong with your app design. Commented Feb 13, 2023 at 21:57
  • The full application code for the graphical part is indicated in the question, indicate where is something wrong in this application? Property var is not cleared from memory. Still, it would not hurt to find out how to clear Unknown memory, which is actually the question. gс() i saw that you wrote how it can be called can you share part of the code how to do it from qml? Commented Feb 13, 2023 at 22:13

2 Answers 2

0

Below is an example of how you may redesign:

  • instead of calling createComponent() it uses a StackView for dynamically creating and destroying Pages with push/pop. Similar approaches could be done with Repeater/ListModel and an appropriate delegate
  • there is deliberately no call to delete - we expect the JSEngine to take care of dynamic destruction and/or recycling of our garbaged objects
  • and, if we must, we can call gc() but, I put it in a Qt.callLater() to ensure that the Page has fully been popped of the stack and had time to destroy
import QtQuick
import QtQuick.Controls
Page {
    property int count: 0
    StackView {
        id: stackView
        anchors.fill: parent
        initialItem: "MainPage.qml"
        onDepthChanged: Qt.callLater(callGC)
    }
    function callGC() {
        gc();
        ++count;
    }
    footer: Frame { Text { text: "gc count %1".arg(count) } }
}

// MainPage.qml
import QtQuick
import QtQuick.Controls
Page {
    header: Frame { Text { text: "Main.qml" } }
    Button {
        anchors.centerIn: parent
        text: "open window1"
        onClicked: {
            stackView.push("SecondPage.qml")
        }
    }
}

// SecondPage.qml
import QtQuick
import QtQuick.Controls

Page {
    header: Frame { Text { text: "SecondPage.qml" } }
    property var name: [ ]
    Button {
        anchors.centerIn: parent
        text: qsTr("destroy window1")
        onClicked: stackView.pop();
    }
    Component.onCompleted: {
        //for (let i=1; i < 1000000; i++) {
        for (let i=1; i < 1000; i++) {
            name.push();
        }
    }
}

You can Try it Online!

Sign up to request clarification or add additional context in comments.

4 Comments

It is very interesting dessision I will try it to use. Thank you for your answer you helped me a lot
There is interesting thing, when I use your scheme Unknown memory(property var) actualy rellese normaly and no increasing. This is the best answer from all:) Thanks again
Thanks @ArtemRedko, however, generally, you should rely on the fact that Javascript default garbage collector is designed to release physical memory when it determines to be the best/optimal time to do so. Whether physical memory is or is not available, does not matter. Javascript will keep track of it all, and, will cede the memory when things become critical, else it will release it on demand. As I tried to indicate, whilst you can call gc(), you need to be sure you know why you are calling it.
Yes, I agree, this is logical, but the property var memory remained in this case as used (memory leak), because the sequential opening of windows and increasing the occupied memory did not free it, and ultimately led to the device freezing, possibly due to the fact that the requested amount of memory exceeded the allowable allocation, as an assumption
0

I jumped to conclusions gc() does not release the memory of the "property var", the only way I found to do this is to redefine the variable "property var" with int type, that is, assign it zero, then call gc() and Unknown memory under this variable will be released

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.