diff options
author | Fabian Kosmale <fabian.kosmale@qt.io> | 2023-04-27 14:22:30 +0200 |
---|---|---|
committer | Fabian Kosmale <fabian.kosmale@qt.io> | 2023-04-28 05:41:06 +0200 |
commit | 0a333bc7e5ae9db1d289a65aa7eef46ae7916936 (patch) | |
tree | ff16c65ad35dc9f9b183443485d94a7146e5e7c9 /src/qml/qml/qqmlengine.cpp | |
parent | 407675b1913a5138c636a730cf3f6a65ffed87fb (diff) |
QQmlData: Implement markAsDeleted without recursion
While a normal QML scene should not feature extremely deep object trees,
one can still encounter them in some test cases.
Those test cases might then run out of (C++) stack space with the
previous recursive version of markAsDeleted.
Thus, we change the implementation to use an explicit workqueue instead
of relying on recursion. This changes the visitation order, but code is
not supposed to rely on the order of Component.onDestroyed calls anyway
(and we keep at least the order in so far that the parent emits the
"signal" before it's children.
Pick-to: 6.5
Change-Id: I93b30cc26b984d1a21cff92df1dd68cd45e67477
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Diffstat (limited to 'src/qml/qml/qqmlengine.cpp')
-rw-r--r-- | src/qml/qml/qqmlengine.cpp | 14 |
1 files changed, 9 insertions, 5 deletions
diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp index 9c7d9f302e..d7542c09fc 100644 --- a/src/qml/qml/qqmlengine.cpp +++ b/src/qml/qml/qqmlengine.cpp @@ -386,11 +386,15 @@ int QQmlData::endpointCount(int index) void QQmlData::markAsDeleted(QObject *o) { - QQmlData::setQueuedForDeletion(o); - - QObjectPrivate *p = QObjectPrivate::get(o); - for (QList<QObject *>::const_iterator it = p->children.constBegin(), end = p->children.constEnd(); it != end; ++it) { - QQmlData::markAsDeleted(*it); + QVarLengthArray<QObject *> workStack; + workStack.push_back(o); + while (!workStack.isEmpty()) { + auto currentObject = workStack.last(); + workStack.pop_back(); + QQmlData::setQueuedForDeletion(currentObject); + auto currentObjectPriv = QObjectPrivate::get(currentObject); + for (QObject *child: std::as_const(currentObjectPriv->children)) + workStack.push_back(child); } } |