Home > Mobile >  QMainWindow with member QWidget and QLayout crashes on exit, how to fix that?
QMainWindow with member QWidget and QLayout crashes on exit, how to fix that?

Time:04-15

The following is a single-file QWidget program.

//main.cpp
#include <QApplication>
#include <QMainWindow>
#include <QVBoxLayout>
#include <QLabel>
class MainWindow:public QMainWindow{
    QLabel lb;
    QWidget wgt;
    QVBoxLayout lout{&wgt};
public:
    MainWindow(){
        lout.addWidget(&lb);//line A
        setCentralWidget(&wgt);
    }
};
int main(int argc, char *argv[]){
    QApplication a(argc, argv);
    MainWindow w;
    w.show();
    return a.exec();
}

The program crashes on exit. The function-call trace on crash is

system calls
QObjectPrivate::deleteChildren()
QWidget::~QWidget()
QMainWindow::~MainWindow
main

If line A is removed then there is no crash.

I want to figure out what causes the crash, and how to use member QWidget and QLayout without having a crash. Thanks in advance.

CodePudding user response:

When you work with QT and C in most of cases you should use new to create QT objects. QT has its own parent ownership model - more you can read here.

Problem is with setCentralWidget(&wgt); because:

  1. setCentralWidges makes that MainWindow becomes parent of wgt.
  2. in main function, at the end of scope, w instance is deleted as local variable, so it calls destructors on its children (it is done by QMainWindow destructor), i.e. - wgt as child of MainWindow is deleted. After destructor of MainWindow is called, all data members are destroyed in reverse order of their creations, so wgt is deleted again leading to crash.

CodePudding user response:

Descendants of QObject should be created dynamically, if they are added to some parent. This is because their ownership passes on to the parent, and they get deleted by their parent class once that gets deleted. This means that in your case, the objects get deleted twice: once via the child destruction mechanism, and once by MainWindow' going out of scope calling the destructor of its members.

That you have to use & in addWidget and setCentralWidget should give you a hint already, as this means that these methods takes the pointer to these objects.

See Qt: Object Trees & Ownership for more details.

  •  Tags:  
  • c qt
  • Related