Details
-
Bug
-
Resolution: Out of scope
-
Not Evaluated
-
None
-
6.3.0, 6.3.1
-
None
Description
Introduced by QTBUG-33908.
Let's have a class for the child item:
class TestWidget : public QWidget { Q_OBJECT public: TestWidget(QWidget *parent = nullptr) : QWidget(parent) { } ~TestWidget() { cancelLoad(); } signals: void updated() const; private: void cancelLoad() { emit updated(); } };
and a class for the parent item:
class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(QWidget *parent = nullptr) : QMainWindow(parent) { m_test = new TestWidget(this); connect(m_test, &TestWidget::updated, this, &MainWindow::updateContent); } private: void updateContent() { } TestWidget *m_test = nullptr; };
On main window close the program crashes with the following error:
ASSERT failure in MainWindow: "Called object is not of the correct type (class destructor may have already run)", file /mnt/store/Development/Qt/6.3.1/gcc_64/include/QtCore/qobjectdefs_impl.h, line 155
1 __GI_raise raise.c 50 0x7ffff6e7700b 2 __GI_abort abort.c 79 0x7ffff6e56859 3 qAbort qglobal.cpp 3397 0x7ffff72d541a 4 qt_message_fatal qlogging.cpp 1879 0x7ffff72d5b4c 5 QMessageLogger::fatal qlogging.cpp 881 0x7ffff72d5b4c 6 qt_assert_x qlogging.h 97 0x7ffff72d5414 7 QtPrivate::assertObjectType<MainWindow> qobjectdefs_impl.h 155 0x5555555581f4 8 QtPrivate::FunctorCall<QtPrivate::IndexesList<>, QtPrivate::List<>, void, void (MainWindow:: *)()>::call(void (MainWindow:: *)(), MainWindow *, void * *) qobjectdefs_impl.h 170 0x5555555580e0 9 QtPrivate::FunctionPointer<void (MainWindow:: *)()>::call<QtPrivate::List<>, void>(void (MainWindow:: *)(), MainWindow *, void * *) qobjectdefs_impl.h 208 0x555555558097 10 QtPrivate::QSlotObject<void (MainWindow:: *)(), QtPrivate::List<>, void>::impl(int, QtPrivate::QSlotObjectBase *, QObject *, void * *, bool *) qobjectdefs_impl.h 419 0x555555557ffd 11 QtPrivate::QSlotObjectBase::call qobjectdefs_impl.h 399 0x7ffff73c229a 12 doActivate<false> qobject.cpp 3921 0x7ffff73c229a 13 TestWidget::updated main.moc 133 0x555555557733 14 TestWidget::cancelLoad main.cpp 23 0x555555557a92 15 TestWidget::~TestWidget main.cpp 14 0x555555557a22 16 TestWidget::~TestWidget main.cpp 15 0x555555557a58 17 QObjectPrivate::deleteChildren qlist.h 415 0x7ffff73bc20a 18 QWidget::~QWidget qwidget.cpp 1525 0x7ffff7a6aee8 19 MainWindow::~MainWindow main.cpp 27 0x55555555826e 20 main main.cpp 50 0x555555557497
This doesn't happen on pure objects (non-widgets), because ~QObject() disconnects signals and then deletes children, but ~QWidget() deletes children before signals disconnection in ~QObject().
Another example is a class derived from QGraphicsScene with a slot that is connected to signals from graphics objects. ~QGraphicsScene() calls QGraphicsScene::clear() which deletes all graphics items without any prior disconnection.
In general, any class A that destroys some "children" that could be connected to an instance of class B that is derived from A could be affected.
To summarize current problems with signals and slots:
1. From the sender's view: (1) an object must not send signals from its destructor and (2) must not call any function that could send a signal or (3) disconnect in the destructor all signals of this class type.
While (1) could be done, how do we ensure (2)?
How to disconnect only signals only from a specific type (3)? Adding `disconnect()` statements manually in the destructor requires a lot of work, it's a boilerplate code and error-prone.
2. From the receiver's view: an object must disconnect all slots of this class type. Again, how to do that?
3. From the user's of senders and receivers: the above changes should be done to all classes, including Qt code and other libraries. As this is almost impossible, one can only use signal-slot connection if: (1) a sender isn't a (indirect) child of the receiver or (2) sender won't emit signals in destructor and won't call any function that emits. (1) is hard, because an item could be moved to a different parent and that new parent could be a receiver. (2) is almost impossible, especially if the source code isn't available.
Attachments
Issue Links
- relates to
-
QTBUG-105746 Fix design flaw which might cause slots to be invoked on partially destroyed objects
-
- Reported
-