-
Bug
-
Resolution: Out of scope
-
Not Evaluated
-
None
-
6.5.9, 6.8.4, 6.9.1, 6.10.0 Beta2
-
Windows 10 22H2, MSVC 2022 x64
Code
#include <QApplication> #include <QWidget> #include <QTimer> #include <QDebug> class ChildObj : public QWidget { Q_OBJECT public: explicit ChildObj(QWidget* parent = nullptr) : QWidget(parent) {} ~ChildObj() { qDebug("ChildObj::~ChildObj()"); } }; class ParentObj : public QWidget { Q_OBJECT public: explicit ParentObj(QWidget* parent = nullptr): QWidget(parent) { auto childObj = new ChildObj(this); // Functor-based connection: Slot is called after ParentObj is destroyed (Not expected) connect(childObj, &QObject::destroyed, this, &ParentObj::onChildDestroyed); // String-based connection: Slot is NOT called after ParentObj is destroyed (Expected) //connect(childObj, SIGNAL(destroyed(QObject*)), this, SLOT(onChildDestroyed(QObject*))); } ~ParentObj() { qDebug("ParentObj::~ParentObj()"); } private slots: void onChildDestroyed(QObject *obj) { qDebug() << "ParentObj::onChildDestroyed():" << obj; } }; int main(int argc, char* argv[]) { QApplication a(argc, argv); auto pObj = new ParentObj(); QTimer::singleShot(1000, &a, [&]() { pObj->deleteLater(); qApp->quit(); }); return a.exec(); } #include "main.moc"
Outcomes
We get an assertion 1s after running the code above. Windows lets us ignore the assertion and continue executing, and we see this:
ParentObj::~ParentObj() ChildObj::~ChildObj() ASSERT failure in ParentObj: "Called object is not of the correct type (class destructor may have already run)", file C:\Qt\6.10.0\msvc2022_64\include\QtCore/qobjectdefs_impl.h, line 106 ParentObj::onChildDestroyed(): QWidget(0x2bcd85b3eb0)
In summary, Qt still tried to run the onChildDestroyed slot even after the ParentObj's destructor had run.
Note: This problem doesn't occur if...
- ...we use the string-based connection, OR
- ...the objects inherit QObject instead of QWidget