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

QMainWindow::restore() can create a state incoherent with QDockAreaLayoutInfo::insertGap()

    XMLWordPrintable

Details

    • Bug
    • Resolution: Done
    • P1: Critical
    • 4.7.1
    • 4.5.0
    • Widgets: Main Window
    • None
    • ce4522cb341340e98427d678664ea84761e3ca07

    Description

      QMainWindow::restore() can fill a dock area with QDockAreaLayoutInfo that have neither a subinfo, nor a widgetItem. This happens when the dock widgets do not exist yet when QMainWindow::restore() is called.

      The code of QDockAreaLayoutInfo::insertGap() call the function widget() on the widgetItem, even if it is null. :

                  QDockAreaLayoutInfo *subinfo = item.subinfo;
                  QLayoutItem *widgetItem = item.widgetItem;
                  QRect r = subinfo == 0 ? dockedGeometry(widgetItem->widget()) : subinfo->rect;
      

      The following code reproduce the initial conditions of the crash, but is unable to reproduce the crash (the condition path.count() > 1 is not respected in QDockAreaLayoutInfo::insertGap()). Set a breakpoint in QDockAreaLayoutInfo::insertGap() to see that the QDockAreaLayoutInfo in the item_list have (subinfo == 0 && widgetItem ==0).

      #include <QtGui>
      
      int main(int argc, char *argv[])
      {
          QApplication app(argc, argv);
      
          QDockWidget *customDockWidget = new QDockWidget();
          customDockWidget->setObjectName("customDockWidget");
      
          QDockWidget *customDockWidget1 = new QDockWidget();
          customDockWidget1->setObjectName("customDockWidget1");
      
          QDockWidget *customDockWidget2 = new QDockWidget();
          customDockWidget2->setObjectName("customDockWidget2");
      
          QMainWindow window;
          window.setDockOptions(QMainWindow::AnimatedDocks);
          window.setDockNestingEnabled(true);
          window.addDockWidget(Qt::LeftDockWidgetArea, customDockWidget, Qt::Vertical);
          window.addDockWidget(Qt::LeftDockWidgetArea, customDockWidget1, Qt::Horizontal);
          window.addDockWidget(Qt::LeftDockWidgetArea, customDockWidget2, Qt::Horizontal);
          window.show();
          app.exec();
          QByteArray state = window.saveState();
      
          QMainWindow otherWindow;
          otherWindow.setDockOptions(QMainWindow::AnimatedDocks);
          otherWindow.restoreState(state);
          otherWindow.addDockWidget(Qt::RightDockWidgetArea, new QDockWidget(), Qt::Horizontal);
          otherWindow.setCentralWidget(new QPushButton("move the the left"));
          otherWindow.show();
      
          return app.exec();
      }
      

      Here is a trace of the crash in Valgrind:

      ==17364== Invalid read of size 8
      ==17364== at 0xF0BD91F: QDockAreaLayoutInfo::insertGap(QList<int>, QLayoutItem*) (qdockarealayout.cpp:1330)
      ==17364== by 0xF0BDC41: QDockAreaLayout::insertGap(QList<int>, QLayoutItem*) (qdockarealayout.cpp:2706)
      ==17364== by 0xF0E0AF0: QMainWindowLayoutState::insertGap(QList<int>, QLayoutItem*) (qmainwindowlayout.cpp:446)
      ==17364== by 0xF0E5B7E: QMainWindowLayout::hover(QLayoutItem*, QPoint const&) (qmainwindowlayout.cpp:1925)
      ==17364== by 0xF0AC6E5: QDockWidgetPrivate::mouseMoveEvent(QMouseEvent*) (qdockwidget.cpp:876)
      ==17364== by 0xF0AE9B9: QDockWidget::event(QEvent*) (qdockwidget.cpp:1437)
      ==17364== by 0xED083CD: QApplicationPrivate::notify_helper(QObject*, QEvent*) (qapplication.cpp:4056)
      ==17364== by 0xED0D88A: QApplication::notify(QObject*, QEvent*) (qapplication.cpp:3758)
      ==17364== by 0x7D4CC95: QTestApplication::notify(QObject*, QEvent*) (QTestApplication.cpp:79)
      ==17364== by 0xE8470B2: QCoreApplication::notifyInternal(QObject*, QEvent*) (qcoreapplication.cpp:610)
      ==17364== by 0xED0CC30: QApplicationPrivate::sendMouseEvent(QWidget*, QMouseEvent*, QWidget*, QWidget*, QWidget**, QPointer<QWidget>&) (qcoreapplication.h:216)
      ==17364== by 0xED70C4C: QETWidget::translateMouseEvent(_XEvent const*) (qapplication_x11.cpp:4409)
      ==17364== by 0xED6F1EC: QApplication::x11ProcessEvent(_XEvent*) (qapplication_x11.cpp:3550)
      ==17364== by 0xED95C92: x11EventSourceDispatch(_GSource*, int (void*), void*) (qguieventdispatcher_glib.cpp:146)
      ==17364== by 0x3C8DE2EF52: g_main_context_dispatch (in /lib64/libglib-2.0.so.0.1400.6)
      ==17364== by 0x3C8DE3224C: ??? (in /lib64/libglib-2.0.so.0.1400.6)
      ==17364== by 0x3C8DE3277D: g_main_context_iteration (in /lib64/libglib-2.0.so.0.1400.6)
      ==17364== by 0xE870D0D: QEventDispatcherGlib::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) (qeventdispatcher_glib.cpp:327)
      ==17364== by 0xED95AAE: QGuiEventDispatcherGlib::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) (qguieventdispatcher_glib.cpp:202)
      ==17364== by 0xE8464A4: QEventLoop::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) (qeventloop.cpp:149)
      ==17364== by 0xE84670B: QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>) (qeventloop.cpp:201)
      ==17364== by 0xE848378: QCoreApplication::exec() (qcoreapplication.cpp:888)
      ==17364== by 0x7D49694: Tapplication::start() (Tapplication.cpp:684)
      ==17364== by 0x40D4E1: appmain() (TTestApp.cpp:1333)
      ==17364== by 0x41BDE0: main (main.cpp:74)
      ==17364== Address 0x0 is not stack'd, malloc'd or (recently) free'd
      ==17364==
      ==17364== Process terminating with default action of signal 11 (SIGSEGV): dumping core
      ==17364== Access not within mapped region at address 0x0
      ==17364== at 0xF0BD91F: QDockAreaLayoutInfo::insertGap(QList<int>, QLayoutItem*) (qdockarealayout.cpp:1330)
      ==17364== by 0xF0BDC41: QDockAreaLayout::insertGap(QList<int>, QLayoutItem*) (qdockarealayout.cpp:2706)
      ==17364== by 0xF0E0AF0: QMainWindowLayoutState::insertGap(QList<int>, QLayoutItem*) (qmainwindowlayout.cpp:446)
      ==17364== by 0xF0E5B7E: QMainWindowLayout::hover(QLayoutItem*, QPoint const&) (qmainwindowlayout.cpp:1925)
      ==17364== by 0xF0AC6E5: QDockWidgetPrivate::mouseMoveEvent(QMouseEvent*) (qdockwidget.cpp:876)
      ==17364== by 0xF0AE9B9: QDockWidget::event(QEvent*) (qdockwidget.cpp:1437)
      ==17364== by 0xED083CD: QApplicationPrivate::notify_helper(QObject*, QEvent*) (qapplication.cpp:4056)
      ==17364== by 0xED0D88A: QApplication::notify(QObject*, QEvent*) (qapplication.cpp:3758)
      ==17364== by 0x7D4CC95: QTestApplication::notify(QObject*, QEvent*) (QTestApplication

      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)
            poulain Benjamin Poulain (closed Nokia identity) (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved:

              Gerrit Reviews

                There are no open Gerrit changes