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:
- setCentralWidges makes that MainWindow becomes parent of
wgt
. - 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 byQMainWindow
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, sowgt
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.