Details
-
Bug
-
Resolution: Fixed
-
P1: Critical
-
6.7.0, 6.7.1, 6.8
-
None
-
-
006cbf658 (dev), f0f9cc602 (6.8), 0673dde3f (6.7)
Description
Steps to reproduce:
- Run the program below:
#include <iostream> #include <QApplication> #include <QTabWidget> #include <QWindow> #include <QQuickWidget> class MyWindow : public QWindow { public: MyWindow() { std::cerr << "MyWindow::MyWindow(). this=" << std::hex << this << std::endl; } ~MyWindow() { std::cerr << "MyWindow::~MyWindow(). this=" << std::hex << this << std::endl; } }; int main(int argc, char *argv[]) { QApplication app(argc, argv); QTabWidget tab_widget; tab_widget.show(); const auto w1 = QWidget::createWindowContainer(new MyWindow(), &tab_widget); tab_widget.addTab(w1, QStringLiteral("MyWindow tab")); // Trigger condition. During the execution of this statement MyWindow will unexpectedly // be deleted. tab_widget.addTab(new QQuickWidget(), QStringLiteral("QQuickWidget tab")); return QCoreApplication::exec(); }
Expected result:
The program runs
Actual result:
The program crashes.
The program crashes because the MyWindow instanced added via QWidget::createWindowContainer() is unexpectedly deleted when the second tab, "QQuickWidget tab", is added. This happens because of the call to newtlw->destroy() in the following code from https://code.qt.io/cgit/qt/qtbase.git/commit/?id=68a4c5da9a080101cccd8a3b2edb1c908da0ca8e
void QWidget::setParent(QWidget *parent, Qt::WindowFlags f) { ... if (oldtlw != newtlw) { ... if (q_evaluateRhiConfig(this, nullptr, &surfaceType)) { ... if (recreate) { const auto windowStateBeforeDestroy = newtlw->windowState(); const auto visibilityBeforeDestroy = newtlw->isVisible(); newtlw->destroy(); // <--- Causes the window created with QWidget::createWindowContainer() to be deleted newtlw->create(); Q_ASSERT(newtlw->windowHandle()); newtlw->windowHandle()->setWindowStates(windowStateBeforeDestroy); QWidgetPrivate::get(newtlw)->setVisible(visibilityBeforeDestroy); }
The stacktrace for the destruction of the MyWindow instance:
MyWindow::~MyWindow(MyWindow * const this) (/home/ts/src/easyviz/qtutility/examples/example2.cc:15) MyWindow::~MyWindow(MyWindow * const this) (/home/ts/src/easyviz/qtutility/examples/example2.cc:16) libQt6Core.so.6!QObjectPrivate::deleteChildren(QObjectPrivate * const this) (/home/ts/src/qt5-2/qtbase/src/corelib/kernel/qobject.cpp:2216) libQt6Core.so.6!QObject::~QObject(QObject * const this) (/home/ts/src/qt5-2/qtbase/src/corelib/kernel/qobject.cpp:1168) libQt6Gui.so.6!QWindow::~QWindow(QWindow * const this) (/home/ts/src/qt5-2/qtbase/src/gui/kernel/qwindow.cpp:203) libQt6Widgets.so.6!QWidgetWindow::~QWidgetWindow(QWidgetWindow * const this) (/home/ts/src/qt5-2/qtbase/src/widgets/kernel/qwidgetwindow.cpp:156) libQt6Widgets.so.6!QWidgetWindow::~QWidgetWindow(QWidgetWindow * const this) (/home/ts/src/qt5-2/qtbase/src/widgets/kernel/qwidgetwindow.cpp:156) libQt6Widgets.so.6!QWidgetPrivate::deleteTLSysExtra(QWidgetPrivate * const this) (/home/ts/src/qt5-2/qtbase/src/widgets/kernel/qwidget.cpp:1705) libQt6Widgets.so.6!QWidget::destroy(QWidget * const this, bool destroyWindow, bool destroySubWindows) (/home/ts/src/qt5-2/qtbase/src/widgets/kernel/qwidget.cpp:12585) libQt6Widgets.so.6!QWidget::setParent(QWidget * const this, QWidget * parent, Qt::WindowFlags f) (/home/ts/src/qt5-2/qtbase/src/widgets/kernel/qwidget.cpp:10929) libQt6Widgets.so.6!QWidget::setParent(QWidget * const this, QWidget * parent) (/home/ts/src/qt5-2/qtbase/src/widgets/kernel/qwidget.cpp:10710) libQt6Widgets.so.6!QLayout::addChildWidget(QLayout * const this, QWidget * w) (/home/ts/src/qt5-2/qtbase/src/widgets/kernel/qlayout.cpp:863) libQt6Widgets.so.6!QStackedLayout::insertWidget(QStackedLayout * const this, int index, QWidget * widget) (/home/ts/src/qt5-2/qtbase/src/widgets/kernel/qstackedlayout.cpp:191) libQt6Widgets.so.6!QStackedWidget::insertWidget(QStackedWidget * const this, int index, QWidget * widget) (/home/ts/src/qt5-2/qtbase/src/widgets/widgets/qstackedwidget.cpp:146) libQt6Widgets.so.6!QTabWidget::insertTab(QTabWidget * const this, int index, QWidget * w, const QIcon & icon, const QString & label) (/home/ts/src/qt5-2/qtbase/src/widgets/widgets/qtabwidget.cpp:440) libQt6Widgets.so.6!QTabWidget::insertTab(QTabWidget * const this, int index, QWidget * w, const QString & label) (/home/ts/src/qt5-2/qtbase/src/widgets/widgets/qtabwidget.cpp:419) libQt6Widgets.so.6!QTabWidget::addTab(QTabWidget * const this, QWidget * child, const QString & label) (/home/ts/src/qt5-2/qtbase/src/widgets/widgets/qtabwidget.cpp:363) main(int argc, char ** argv) (/home/ts/src/easyviz/qtutility/examples/example2.cc:31)
The problem reproduces on both the platforms I have access to, Linux and Windows, with exactly the same stacktrace.