Details
-
Bug
-
Resolution: Fixed
-
P1: Critical
-
6.2.2, 6.5.8, 6.8.2
-
ubuntu24.04, qtcreator 15.0.1, gcc12.3.0
-
-
76188bc34 (6.8.3)
Description
I ran the provided test code from the key customer and confirmed that a memory leak occurs when executing the test. The test was performed on version v6.2.2, and the same issue occurs in not only v5.5.18 but also v6.8.2.
(os: ubuntu24.04, qt version: v6.2.2, v6.8.2, v5.5.18)
I have attached the heaptrack results from both v6.2.2 and v6.8.2.
From the heaptrack analysis, I observed that in the "consumed page" section, the memory usage continuously increases at a steady rate due to the connectImpl function.(yellow in below image)
Even though the same test code was executed, the "Largest Memory Leaks" section on the "summary page" sometimes shows results and sometimes doesn't. This might be a separate issue, so it can be considered for reference only.
Now, getting back to the main issue, while analyzing the memory leak, I noticed that the setModel function in the "QQuickItemView" class was present in the call stack. Upon checking, I found that the disconnect and connect functions do not match as pairs.
If we consider disconnect and Private::disconnect as disconnect, and connect and Private::connect as connect, the delegateChanged item only has connect but no disconnect.
After fixing this issue and running the heaptrack test again, the graph in the "consumed page" now resembles a near-horizontal line, which seems to be the expected result.
I would like to confirm whether this is the intended implementation or a bug.
If it is the intended behavior, please share information on which part needs to be modified to fix the memory leak.
- test code Qml file
(png file is not attached, it could be anything in my opnion)import QtQuick Window { width: 640 height: 480 visible: true title: qsTr("Hello World") Item { id: defaultLayers property int indexValue : 0 property int indexCount : 0 Item { id: indicatorTest x: 20 y: 20 width: 90 height: 244 Component { id: indicatorComponent Image { id: componentImage width: 12 height: 12 source: "file:/Users/jaejin/Downloads/penguin.png" } } ListView { id: indicatorListview width: 12 height: (defaultLayers.indexValue * 12) + ((defaultLayers.indexValue - 1) * 6) anchors.centerIn: parent model: defaultLayers.indexValue delegate: indicatorComponent spacing: 6 focus: true } Timer { id: testTimer interval: 100 running: true repeat: true onTriggered: { defaultLayers.indexValue = (defaultLayers.indexValue + 1) % 10 defaultLayers.indexCount = defaultLayers.indexCount + 1 if (defaultLayers.indexCount >= 20000) { Qt.quit(); } } } } Component.onCompleted: { testTimer.start() } }}
what I changed code
in qtdeclarative repo, src/quick/items/qquickitemview.cpp
// code placeholder void QQuickItemView::setModel(const QVariant &m) { .... if (d->model) { disconnect(... modelUpdated ...); disconnect(... initItem ...); disconnect(... createdItem ...); disconnect(... destroyItem ...); if ( ... delegateModel = ... (d->model)) { disconnect(delegateModel, ... itemPooled ...); disconnect(delegateModel, ... itemReused ...); // could not find delegateChanged disconnect // QObjectPrivate::disconnect(delegateModel, &QQmlDelegateModel::delegateChanged, d, &QQuickItemViewPrivate::applyDelegateChanged); } } .... .... if (d->model) { d->bufferMode ... connect(d->model, ... createdItem ...); connect(d->model, ... initItem ...); connect(d->model, ... destroyingItem ...); if (... delegateModel = ... (d->model)) { connect(delegateModel, ... itemPooled ...); connect(delegateModel, ... itemReused ... ); } if (isComponentComplete()) { ... } connect(... modelUpdated ... ) if ( ... dataModel = ...(d->model)) QObjectPrivate::connect(dataModel, &QQmlDelegateModel::delegatedChanged, d, &QQuickItemViewPrivate::applyDelegateChange); emit ... } ... }
- test with below command
- QT_WAYLAND_DISABLE_WINDOWDECORATION=1 WAYLAND_DISPLAY=wayland-1 XDG_RUNTIME_DIR=/run/user/1000 QT_QPA_PLATFORM=wayland
Attachments
For Gerrit Dashboard: QTBUG-134320 | ||||||
---|---|---|---|---|---|---|
# | Subject | Branch | Project | Status | CR | V |
631268,2 | QQuickItemView: Disconnect forgotten model signal on model change | tqtc/lts-6.5 | qt/tqtc-qtdeclarative | Status: NEW | 0 | 0 |
631249,5 | QQuickItemView: Disconnect forgotten model signal on model change | 6.8.3 | qt/qtdeclarative | Status: MERGED | +2 | 0 |