Details
-
Bug
-
Resolution: Unresolved
-
P1: Critical
-
6.9.0
-
None
-
MacOS 15, arm64, expected to be universally affected.
Description
Similar but substantially different from QTBUG-118188,
After model-view model/delegate destruction, items are not cleaned up fully and trigger the bindings(to already long invalid/destroyed things).
This is one reproducer of multiple encountered in various circumstances, on model move/DnD/repopulation, in/after DnD modal event loops, window lifetimes.
Snippet from reproducer zip:
Repeater { delegate: Item { id: rowDelegate required property var modelData property real pixelScale: 11 Repeater { model: rowDelegate.modelData delegate: Label { elide: Text.ElideRight property var scaleProvider: rowDelegate // This binding is alive after destruction. width: 10 * scaleProvider.pixelScale
shutting down, destroying module contents qml: Repeater destroyed qml: Delegate destroyed qml: Sub Delegate destroyed ui/module destruction/unload completed QFontDatabase: Must construct a QGuiApplication before accessing QFontDatabase Abort trap: 6
qt_message(QtMsgType, QMessageLogContext const&, char const*, char*) QMessageLogger::fatal(char const*, ...) const QFontDatabasePrivate::ensureFontDatabase() (.cold.1) QFontDatabasePrivate::ensureFontDatabase() QFontDatabasePrivate::findFont(QFontDef const&, int, bool) QFontDatabasePrivate::load(QFontPrivate const*, int) QFontPrivate::engineForScript(int) const QFontMetricsF::height() const QQuickTextPrivate::updateSize() QQuickText::geometryChange(QRectF const&, QRectF const&) QQuickLabel::geometryChange(QRectF const&, QRectF const&) QQuickItem::setWidth(double) QObjectCompatProperty<QQuickItemPrivate, double, &QQuickItemPrivate::_qt_property_width_offset(), &QQuickItemPrivate::setWidth(double), &QQuickItemPrivate::widthChanged(), nullptr>::bindingWrapper(QMetaType, QUntypedPropertyData*, QtPrivate::QPropertyBindingFunction) QPropertyObserverPointer::evaluateBindings(QVarLengthArray<QPropertyBindingPrivatePtr, 256ll>&, QBindingStatus*) QPropertyBindingPrivate::evaluateRecursive(QVarLengthArray<QPropertyBindingPrivatePtr, 256ll>&, QBindingStatus*) QQmlPropertyBindingJS::expressionChanged() QQmlNotifier::emitNotify(QQmlNotifierEndpoint*, void**) void doActivate<false>(QObject*, int, void**) QQmlData::destroyed(QObject*) QObject::~QObject() QQuickItem::~QQuickItem() QQmlPrivate::QQmlElement<QQuickItem>::~QQmlElement() QObjectPrivate::deleteChildren() QObject::~QObject() QGuiApplication::~QGuiApplication() main
...
The core issues here is the lifetime of delegate/dynamic items(and bindings) is
1) not documented
2) extended beyond what is reasonably expected
3) impossible to reason about or handle in (unrelated independent modules') c++ models and other c++-based data(and qt/qml ui) management code
(4? might cause problems for custom c++-based delegates?)
Changes from patches.zip fix this issues as well as QTBUG-118188
Adding
qApp->sendPostedEvents(0, QEvent::DeferredDelete);
in key places also works around this, but this approach is not scalable nor reasonably applicable to production codebases.
Note: neither processEvents() nor sendPostedEvents() do the same!