Is this object destruction failure?
-
Why does the following program crash when trying to exit the program?
#include <QApplication> #include <QLayout> #include <QLabel> int main(int argc, char *argv[]) { QApplication app(argc, argv); QWidget appWidget; QLabel lblA("A"); QGridLayout layG; layG.addWidget(&lblA, 0, 0); QLabel lblB("B"); QVBoxLayout totalLayout; totalLayout.addLayout(&layG); totalLayout.addWidget(&lblB); appWidget.setLayout(&totalLayout); appWidget.show(); return app.exec(); }but if you dynamically allocate memory for just one of
layGortotalLayoutlayouts, it won't crash.
what is happening here? -
QObjects destroy their children when they are destroyed, and a layout is automatically the parent of any sub-layout added to it.Stack objects are destroyed in opposite order to their creation, so
totalLayoutgets destroyed first, and it also destroyslayGsince it is its child object in the QObject hierarchy. The next in order islblB, but after itlayGgets destroyed, but it was already deleted so it is a use after free violation and a crash.Dynamically allocating (and leaking) either layout prevents automatic destruction of it so avoids the scenario.
-
N Nima_MJ has marked this topic as solved
-
I get it. but actually QLayout is not responsible for destroying any QWidget that is added to it. QLayouts only destroy QLayouts that are added to them. QWidgets cannot be a "child" of QLayouts. here,
totalLayoutis responsible for removinglayGobject, which is its child. So here what actually causes the crash is as follows when stack unwinds at the end:
First,totalLayout's destructor is called.
Second, in the destructor,totalLayoutevokes "delete" operator onlayG(causetotalLayoutis responsible for removinglayGas its child)
and here is the problem.layGis stack-allocated and calling "delete" operator on a stack-allocated object is not valid.So, if we allocate even one of them on the heap, in both scenarios it obviously would resolve this problem, one by memory leaking and the other by properly deallocating object.
This is true for the widgets too. the only thing different, is that setLayout() function in widgets makes the widget responsible for the life-time of the QLayouts.
Changing the order of Layou creations, in this case matters. If I were to create
totalLayoutbeforelayG, the crash wouldn't have happened. causelayGwould've been properly destroyed beforetotalLayouttried to evoke "delete" operator on it. Though, I'm not sure how it's handled in Qt. -
Don't create widgets and especially layouts on the stack at all to avoid such problems.