Details
-
Bug
-
Resolution: Done
-
P2: Important
-
5.15
-
ec79af7396 (qt/qtdeclarative/dev) ec79af7396 (qt/tqtc-qtdeclarative/dev)
Description
I have a model named InventoryModel. One of its roles is a QObject-derived class named ComponentEntity. I use this role as a required property in the delegate:
ListView { id: listView anchors.fill: parent model: InventoryModel {} delegate: ItemDelegate { width: listView.width text: itemName required property int index required property string itemName required property ComponentEntity entity Component.onDestruction: print("destroying delegate for " + itemName) } }
When removing an item from the model, I get a warning:
removing 1 of "Item 9" from index 9 (entire stack) ending remove of 1 of "Item 9" (entire stack) Destroying ComponentEntity(0x55ff3b74c7e0, name = "Item 9") qrc:/main.qml: Writing to "entity" broke the binding to the underlying model qml: destroying delegate for Item 9
Stack trace leading up to the error:
1 PropertyUpdater::breakBinding qqmldelegatemodel.cpp 953 0x7fffe928667a 2 PropertyUpdater::qt_static_metacall moc_qqmldelegatemodel_p_p.cpp 513 0x7fffe92b81ea 3 PropertyUpdater::qt_metacall moc_qqmldelegatemodel_p_p.cpp 550 0x7fffe92b82f0 4 QMetaObject::metacall qmetaobject.cpp 317 0x7ffff6a909e1 5 doActivate<false> qobject.cpp 3912 0x7ffff6adde80 6 QMetaObject::activate qobject.cpp 3959 0x7ffff6ad6e23 7 QQmlVMEMetaObject::activate qqmlvmemetaobject.cpp 1312 0x7ffff724127e 8 QQmlVMEVariantQObjectPtr::objectDestroyed qqmlvmemetaobject.cpp 190 0x7ffff7242c8d 9 QQmlData::destroyed qqmlengine.cpp 1951 0x7ffff724b5cd 10 QQmlData::destroyed qqmlengine.cpp 747 0x7ffff72486a9 11 QObject::~QObject qobject.cpp 1001 0x7ffff6acf1fd 12 ComponentEntity::~ComponentEntity main.cpp 15 0x55555555a40b 13 ComponentEntity::~ComponentEntity main.cpp 17 0x55555555a43e 14 QtSharedPointer::CustomDeleter<ComponentEntity, QtSharedPointer::NormalDeleter>::execute qsharedpointer_impl.h 187 0x55555555e01d 15 QtSharedPointer::ExternalRefCountWithCustomDeleter<ComponentEntity, QtSharedPointer::NormalDeleter>::deleter qsharedpointer_impl.h 205 0x55555555d59e 16 QtSharedPointer::ExternalRefCountData::destroy qsharedpointer_impl.h 149 0x55555555a029 17 QSharedPointer<ComponentEntity>::deref qsharedpointer_impl.h 458 0x55555555d6ce 18 QSharedPointer<ComponentEntity>::deref qsharedpointer_impl.h 453 0x55555555c1ea 19 QSharedPointer<ComponentEntity>::~QSharedPointer qsharedpointer_impl.h 310 0x55555555b1a4 20 InventoryModel::removeLast main.cpp 56 0x55555555a8ec 21 InventoryModel::qt_static_metacall main.moc 141 0x555555559138 22 InventoryModel::qt_metacall main.moc 178 0x55555555923e 23 QMetaObject::metacall qmetaobject.cpp 317 0x7ffff6a909e1 24 QQmlObjectOrGadget::metacall qqmlobjectorgadget.cpp 51 0x7ffff72bc6fc 25 CallMethod qv4qobjectwrapper.cpp 1319 0x7ffff70f9d6b 26 CallPrecise qv4qobjectwrapper.cpp 1573 0x7ffff70fa854 27 QV4::QObjectMethod::callInternal qv4qobjectwrapper.cpp 2131 0x7ffff70fd2ba 28 QV4::QObjectMethod::virtualCall qv4qobjectwrapper.cpp 2068 0x7ffff70fcd2c 29 QV4::FunctionObject::call qv4functionobject_p.h 202 0x7ffff702f97f 30 QV4::Moth::VME::interpret qv4vme_moth.cpp 757 0x7ffff712c601 31 QV4::Moth::VME::exec qv4vme_moth.cpp 466 0x7ffff712825f 32 QV4::Function::call qv4function.cpp 69 0x7ffff7098dd6 33 QQmlJavaScriptExpression::evaluate qqmljavascriptexpression.cpp 212 0x7ffff72e1356 34 QQmlBoundSignalExpression::evaluate qqmlboundsignal.cpp 224 0x7ffff72779b3 35 QQmlBoundSignal_callback qqmlboundsignal.cpp 361 0x7ffff7278037 36 QQmlNotifier::emitNotify qqmlnotifier.cpp 104 0x7ffff72bbb4e 37 QQmlData::signalEmitted qqmlengine.cpp 834 0x7ffff7248b79 38 doActivate<false> qobject.cpp 3778 0x7ffff6add83c 39 QMetaObject::activate qobject.cpp 3946 0x7ffff6ad6dad 40 QQuickAbstractButton::clicked moc_qquickabstractbutton_p.cpp 630 0x7fffe881bd5d 41 QQuickAbstractButtonPrivate::trigger qquickabstractbutton.cpp 342 0x7fffe8754bce 42 QQuickAbstractButtonPrivate::handleRelease qquickabstractbutton.cpp 182 0x7fffe875425c 43 QQuickControl::mouseReleaseEvent qquickcontrol.cpp 2151 0x7fffe8787e90 44 QQuickItem::event qquickitem.cpp 8208 0x7fffe96168ad 45 QQuickAbstractButton::event qquickabstractbutton.cpp 1035 0x7fffe8756c29 46 QCoreApplicationPrivate::notify_helper qcoreapplication.cpp 1225 0x7ffff6a865d6 47 doNotify qcoreapplication.cpp 1154 0x7ffff6a861a3 48 QCoreApplication::notify qcoreapplication.cpp 1140 0x7ffff6a86102 49 QGuiApplication::notify qguiapplication.cpp 1935 0x7ffff778d5bd 50 QCoreApplication::notifyInternal2 qcoreapplication.cpp 1064 0x7ffff6a86017 51 QCoreApplication::sendEvent qcoreapplication.cpp 1462 0x7ffff6a86ab4 52 QQuickWindowPrivate::deliverMouseEvent qquickwindow.cpp 2020 0x7fffe964026b 53 QQuickWindowPrivate::deliverPointerEvent qquickwindow.cpp 2612 0x7fffe964387f 54 QQuickWindowPrivate::handleMouseEvent qquickwindow.cpp 2427 0x7fffe9642ef9 55 QQuickWindow::mouseReleaseEvent qquickwindow.cpp 2407 0x7fffe9642bf3 56 QWindow::event qwindow.cpp 2341 0x7ffff77a46c2 57 QQuickWindow::event qquickwindow.cpp 1902 0x7fffe963f848 58 QCoreApplicationPrivate::notify_helper qcoreapplication.cpp 1225 0x7ffff6a865d6 59 doNotify qcoreapplication.cpp 1154 0x7ffff6a861a3 60 QCoreApplication::notify qcoreapplication.cpp 1140 0x7ffff6a86102 61 QGuiApplication::notify qguiapplication.cpp 1935 0x7ffff778d5bd 62 QCoreApplication::notifyInternal2 qcoreapplication.cpp 1064 0x7ffff6a86017 63 QCoreApplication::sendSpontaneousEvent qcoreapplication.cpp 1474 0x7ffff6a86af2 64 QGuiApplicationPrivate::processMouseEvent qguiapplication.cpp 2282 0x7ffff778e81f 65 QGuiApplicationPrivate::processWindowSystemEvent qguiapplication.cpp 2002 0x7ffff778d9bc 66 QWindowSystemInterface::sendWindowSystemEvents qwindowsysteminterface.cpp 1169 0x7ffff776a2b7 67 xcbSourceDispatch qxcbeventdispatcher.cpp 105 0x7ffff2df94a8 68 g_main_context_dispatch 0x7ffff56abf9d 69 ?? 0x7ffff56ac220 70 g_main_context_iteration 0x7ffff56ac2c3 71 QEventDispatcherGlib::processEvents qeventdispatcher_glib.cpp 423 0x7ffff6b24d19 72 QXcbGlibEventDispatcher::processEvents qxcbeventdispatcher.cpp 143 0x7ffff2df96ee 73 QEventLoop::processEvents qeventloop.cpp 139 0x7ffff6a824b5 74 QEventLoop::exec qeventloop.cpp 232 0x7ffff6a8281b 75 QCoreApplication::exec qcoreapplication.cpp 1375 0x7ffff6a868e6 76 QGuiApplication::exec qguiapplication.cpp 1867 0x7ffff778d3ce 77 main main.cpp 140 0x555555558f3e
Then, when exiting:
qml: destroying delegate for Item 8 qml: destroying delegate for Item 7 qml: destroying delegate for Item 6 qml: destroying delegate for Item 5 qml: destroying delegate for Item 4 qml: destroying delegate for Item 3 qml: destroying delegate for Item 2 qml: destroying delegate for Item 1 qml: destroying delegate for Item 0 Destroying ComponentEntity(0x55ff3b7f39d0, name = "Item 0") qrc:/main.qml: Writing to "entity" broke the binding to the underlying model Destroying ComponentEntity(0x55ff3b8e5360, name = "Item 1") qrc:/main.qml: Writing to "entity" broke the binding to the underlying model Destroying ComponentEntity(0x55ff3b875b20, name = "Item 2") qrc:/main.qml: Writing to "entity" broke the binding to the underlying model Destroying ComponentEntity(0x55ff3b875d50, name = "Item 3") qrc:/main.qml: Writing to "entity" broke the binding to the underlying model Destroying ComponentEntity(0x55ff3b875f00, name = "Item 4") qrc:/main.qml: Writing to "entity" broke the binding to the underlying model Destroying ComponentEntity(0x55ff3b770cf0, name = "Item 5") qrc:/main.qml: Writing to "entity" broke the binding to the underlying model Destroying ComponentEntity(0x55ff3b770ea0, name = "Item 6") qrc:/main.qml: Writing to "entity" broke the binding to the underlying model Destroying ComponentEntity(0x55ff3b771050, name = "Item 7") qrc:/main.qml: Writing to "entity" broke the binding to the underlying model Destroying ComponentEntity(0x55ff3b771200, name = "Item 8") qrc:/main.qml: Writing to "entity" broke the binding to the underlying model
I can see that this happens because the ComponentEntity object is destroyed before the delegate. However, as the model is informed of the removal in advance, I don't believe I should be getting this warning. The view should take care of destruction of the delegate and freeze the bindings. However, I know that others disagree with me about this. If the solution is to again say that this is up to the user to deal with, then it should be clearly documented that objects used as required properties must outlive the delegate, with an example demonstrating how to do this.
In my case, when the item is removed from InventoryModel, it should be deleted (assuming there are no other references to it, hence why I use QSharedPointer), which is why I don't think it should be necessary to work around Qt here. A hacky workaround for the attached example (note that a 0 ms timer is not sufficient):
Q_INVOKABLE void removeLast() { const int count = rowCount(); if (count == 0) return; auto sharedEntityPtr = mContents.at(count - 1); const QString objectName = sharedEntityPtr->objectName(); onPreItemRemoved(objectName, 1, true, count - 1); mContents.takeLast(); QTimer::singleShot(100, [=]() mutable { qDebug() << ">>>"; sharedEntityPtr.reset(); qDebug() << "<<<"; }); onPostItemRemoved(objectName, 1, true, count - 1); }
Attachments
Issue Links
- relates to
-
QTBUG-82809 Segfault in PropertyUpdater::breakBinding() on application exit
- Closed
-
QTBUG-94113 False alarm about breaking delegate binding
- Closed