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

events triggered by widget destructor can reach already-deleted children, causing a crash

    XMLWordPrintable

Details

    • f8fb064d6b2ad55c66ce1a481e7f829278051fcb

    Description

      //
      // Test program that demonstrates NULL Qt widgets.
      //
      // When a widget is destroyed it's children are also destroyed, but during
      // that process the child list is maintained with the destroyed widgets set
      // to NULL; here is some abbreviated code from qobject.cpp:
      //
      // void QObjectPrivate::deleteChildren()
      // {
      // ...
      // for (int i = 0; i < children.count(); ++i)

      { // currentChildBeingDeleted = children.at(i); // children[i] = 0; // delete currentChildBeingDeleted; // }

      // children.clear();
      // ...
      // }
      //
      // A situation can arise where during the destruction process an event is
      // propagated to these NULL children. In Qt 4.3.1, a warning message is
      // printed to this effect:
      //
      // QApplication::notify: Unexpected null receiver
      //
      // In Qt 4.5.3 this behavior has changed and the NULL children may be
      // de-referenced causing a segmentation fault.
      //
      // This test program creates a top-level widget with two children. When you
      // close the top-level widget the children are destroyed, and the second
      // child attempts to open a modal dialog box in it's destructor. This modal
      // dialog causes an event to be propagated to the first child widget which has
      // already been destroyed.
      //

      #include <QApplication>
      #include <QHBoxLayout>
      #include <QMessageBox>
      #include <QWidget>
      
      #include <iostream>
      
      //
      // Utility function to print out child widget pointers.
      //
      
      void printChildren(QObject* in)
      {
          const QObjectList children = in->children();
          
          for (int i = 0; i < children.size(); ++i)
              std::cout << "child [" << i << "] = " << children[i] << std::endl;
      }
      
      //
      // Widget base class.
      //
      
      class BaseWidget : public QWidget
      {
        public:
        
          QSize sizeHint() const
          {
              return QSize (100, 100);
          }
      };
      
      //
      // First widget.
      //
      
      class Widget1 : public BaseWidget
      {
        public:
        
          ~Widget1()
          {
              std::cout << "Widget1::~Widget1()" << std::endl;
              
              printChildren(parent());
          }
      };
      
      //
      // Second widget. This widget spawns a modal dialog in it's destructor.
      //
      
      class Widget2 : public BaseWidget
      {
        public:
        
          ~Widget2()
          {
              std::cout << "Widget2::~Widget2()" << std::endl;
      
              printChildren(parent());
              
              QMessageBox().exec();
          }
      };
      
      int
      main(int argc, char** argv)
      {
          QApplication app (argc, argv);
          
          //
          // Create the window.
          //
          
          QWidget* window = new QWidget;
          window->setAttribute (Qt::WA_DeleteOnClose);
          
          //
          // Create the widgets.
          //
          
          Widget1* widget1 = new Widget1;
          Widget2* widget2 = new Widget2;
          
          //
          // Layout the widgets.
          //
          
          QHBoxLayout* layout = new QHBoxLayout;
          window->setLayout (layout);
          layout->addWidget (widget1);
          layout->addWidget (widget2);
          
          //
          // Start the application.
          //
          
          printChildren (window);
          
          window->show();
          
          return app.exec();
      }
      

      Attachments

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

        Activity

          People

            vfm Thierry Bastian (closed Nokia identity) (Inactive)
            hubbard Philip Hubbard
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved:

              Gerrit Reviews

                There are no open Gerrit changes