Details
-
Bug
-
Resolution: Fixed
-
P2: Important
-
5.15.12, 6.4.2, 6.5.0 Beta3
-
Windows 10 22H2, MSVC 2019 x64
-
4fbc6dcf4571d0c3bede192e4456a56e7aeeadde
Description
Code
cppobj.h
#ifndef CPPOBJ_H #define CPPOBJ_H #include <QObject> #include <QQmlEngine> #include <QSet> #include <QDebug> class CppObj; extern QSet<CppObj*> globalObjectRegistry; class CppObj : public QObject { Q_OBJECT QML_ELEMENT public: explicit CppObj(QObject *parent = nullptr) : QObject{parent} { qDebug() << "Constructing" << this; globalObjectRegistry << this; } ~CppObj() { qDebug() << "Deleting" << this << "with parent" << parent(); globalObjectRegistry.remove(this); } }; #endif // CPPOBJ_H
main.cpp
#include <QGuiApplication> #include <QQmlApplicationEngine> #include "cppobj.h" QSet<CppObj*> globalObjectRegistry; int main(int argc, char *argv[]) { QGuiApplication app(argc, argv); int returnValue; { QQmlApplicationEngine engine(QUrl("qrc:/main.qml")); returnValue = app.exec(); } qDebug("=== QQmlApplicationEngine has been destroyed ==="); if (globalObjectRegistry.isEmpty()) qDebug("All CppObjs were deleted at shutdown"); else qDebug() << "These CppObjs were not deleted at shutdown:" << globalObjectRegistry; return returnValue; }
main.qml
import QtQuick 2.15 import QtQuick.Window 2.15 import QtQuick.Controls 2.15 import MyCppModule 1.0 Window { width: 640 height: 480 visible: true ListView { anchors.fill: parent model: ListModel { ListElement { name: "Swipe left" } } delegate: SwipeDelegate { id: dg width: 640 Component.onCompleted: console.log(`Created ${dg}`) Component.onDestruction: console.log(`Destroying ${dg}`) swipe.right: Text { id: innerText anchors.right: parent.right text: "Close the app and check the output" Component.onCompleted: console.log(`Created inner ${innerText}`) Component.onDestruction: console.log(`Destroying inner ${innerText}`) // The QML engine will report that this object gets destroyed, but its C++'s destructor won't get called CppObj { id: innerObj Component.onCompleted: console.log(`Created inner ${innerObj}`) Component.onDestruction: console.log(`Destroying inner ${innerObj}`) } } Text { id: outerText text: name Component.onCompleted: console.log(`Created outer ${outerText}`) Component.onDestruction: console.log(`Destroying outer ${outerText}`) // This object will get destroyed properly CppObj { id: outerObj Component.onCompleted: console.log(`Created outer ${outerObj}`) Component.onDestruction: console.log(`Destroying outer ${outerObj}`) } } } } }
Steps to reproduce
- Build and run the attached project
- Swipe the text from the right
- Close the window
Debug output
At startup:
Constructing CppObj(0x1e6bdb98160) qml: Created SwipeDelegate_QMLTYPE_1(0x1e6bd8c66b0) qml: Created outer QQuickText(0x1e6bda642d0) qml: Created outer CppObj(0x1e6bdb98160)
After swiping:
Constructing CppObj(0x1e6bdc68800) qml: Created inner QQuickText(0x1e6bdc47470) qml: Created inner CppObj(0x1e6bdc68800)
After closing window:
qml: Destroying outer CppObj(0x1e6bdb98160) qml: Destroying outer QQuickText(0x1e6bda642d0) qml: Destroying inner CppObj(0x1e6bdc68800) qml: Destroying inner QQuickText(0x1e6bdc47470) qml: Destroying SwipeDelegate_QMLTYPE_1(0x1e6bd8c66b0) Deleting CppObj(0x1e6bdb98160) with parent QObject(0x1e6bda642d0) === QQmlApplicationEngine has been destroyed === These CppObjs were not deleted at shutdown: QSet(CppObj(0x1e6bdc68800))
Observations
- The QML engine reports that the inner object is getting destroyed, but its C++'s destructor is never called
- In contrast, the outer object's C++ destructor does get called while the QML engine is shutting down