Zen
Zen

Reputation: 5520

Memory leak even if I don't create any qml object dynamically?

I want to create a toolbar, which will rotate and expand when hovered. But the memory leak is so serious that may consume arbitrary RAM, the initial memory usage is about 20MB and reaches 300mb after 1000 animations. I just uses basic components, like ListView, Rectangle and MouseArea. Here is the whole source code. I'm new to qml. Any suggestions would be appreciated, Thanks.

//MyListView.qml
//The ListView will expand when activated.
ListView{
id:root
orientation: ListView.Horizontal
property alias list: listModel

width: calcWidth()

signal optionSelected(string option)

function enableItems(big){
    for(var i in root.contentItem.children){
        var child = root.contentItem.children[i]
        if(child.objectName!=="delegate") continue

        if(big){ child.state="big" }
        else child.state=""
    }
}

function calcWidth(){
    var w = 0
    for(var i in root.contentItem.children) {
        var child = root.contentItem.children[i]
        if(child.objectName==="delegate"){
            w+=child.width
        }
    }
    return w
}

model: ListModel{
    id:listModel
}

delegate: Rectangle{
    id: rect
    objectName: "delegate"
    height: parent.height
    width: 0
    color:"transparent"
    border.color:"grey"; border.width:1; radius: 5
    rotation: width/root.height * 360

    states:State{
        name: "big"
        PropertyChanges{
            target: rect;  width: root.height
        }
    }

    transitions: Transition {
        from: "*"
        to: "big"
        reversible: true
        NumberAnimation{
            properties: "width";easing.type: Easing.OutQuad; duration: 400
        }
    }

    Image{
        anchors.fill: parent
        source: imgSrc
    }

    MouseArea{
        anchors.fill: parent
        hoverEnabled: true
        onEntered: enableItems(true)
        onExited: enableItems(false)
        onClicked: root.optionSelected(option)
    }
}
}

//MyRow.qml
Row{
id:root
width: mainImg.width + listView.width
property alias list: listView.list
property alias mainImg: mainImg.source

signal optionSelected(string option)

Image{
    id: mainImg;  height: parent.height;  width: parent.height

    MouseArea{
        anchors.fill: parent
        hoverEnabled: true
        onEntered: listView.enableItems(true)
        onExited: listView.enableItems(false)
    }
}

MyListView{
    id: listView
    height: root.height
    onOptionSelected: root.optionSelected(option)
}
//test memory usage
Timer{
    id: timer
    running: true; interval: 400; repeat: true
    property real times:0
    property bool big :false
    onTriggered: {
        times ++
        big = !big
        listView.enableItems(big)
        console.log(big+""+times)
        if(times>500){
            timer.running = false
            gc()
        }
    }
}
}

//main.qml
Rectangle {
width: 360
height: 360

MyRow{
    height: 128
    mainImg: "qrc:/4.png"
    onOptionSelected: console.log(option)

    Component.onCompleted: {
        list.append({imgSrc:"qrc:/1.png",option:"111"})
        list.append({imgSrc:"qrc:/2.png",option:"222"})
        list.append({imgSrc:"qrc:/3.png",option:"333"})
    }
}
}

Edit1: I was using Qt 5.5.0 + Linux Mint 17.1 + KDE. Everything works fine after I switched to Qt 5.4.2 + windows 10.

Upvotes: 0

Views: 2679

Answers (1)

dtech
dtech

Reputation: 49329

I am not convinced that you have actually established a memory leak. The QML engine will cache and it is a common thing to see memory usage rising by 20-30 mb for no apparent reason.

But the memory leak is serious

Without any concrete numbers, one can only guess what you mean by that. Does memory usage rise with more than 30 MB and keep rising? Does it reach a 100? Or more?

Keep in mind JS is garbage collected, and collection in my own experience is far from logical, at least in QML. Sometimes I get non-referenced objects living all the way through the application life cycle, sometimes I get objects which are still in use when QML decides for some reason to delete them and the result is segfaults and crashes.

BTW you can force garbage collection with gc() and see if that does any good.

As already established in this similar post, the "normal" behavior is that memory will go up to a certain point and then stabilize, which I suspect is also happening in your case. You should investigate further and post concrete numbers, and if necessary - a bug report.

EDIT: I tested your example code on Qt 5.42, memory usage quickly reaches 47.068 MB, and after 500 animations it is still there, hasn't moved up even a single kb according to the task manager, it actually goes down a little if the animation is stopped, and returns to 47.068 MB if resumed.

With Qt 5.5 it stabilizes at 51.672 MB

In case you are running literally the same code, your Qt version may have a bug.

Upvotes: 2

Related Questions