Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-138852

Functor-based connections don't auto-disconnect correctly

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Out of scope
    • Icon: Not Evaluated Not Evaluated
    • None
    • 6.5.9, 6.8.4, 6.9.1, 6.10.0 Beta2
    • Core: Object Model
    • 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

        No reviews matched the request. Check your Options in the drop-down menu of this sections header.

            thiago Thiago Macieira
            skoh-qt Sze Howe Koh
            Votes:
            1 Vote for this issue
            Watchers:
            6 Start watching this issue

              Created:
              Updated:
              Resolved:

                There are no open Gerrit changes