Program Crash on Exit
I've run into an odd problem in a program interface that I've been playing with to learn how to create an interface. After some work, I finally had the interface the way that I wanted it but when I exit the program, it crashes (and then relaunches). I've looked through the code and I'm not sure why this is happening. The program seems to die with a bad memory access error when it attempts to delete the buttonLayout object.
I've posted the MainWindow class code below.
setWindowTitle("Two Button Test"); messageLayout = new QHBoxLayout; messageLayout->setGeometry(QRect(10, 10, 731, 31)); buttonLayout = new QHBoxLayout; buttonLayout->setGeometry(QRect(10, 489, 731, 41)); mapBoard = new QHBoxLayout; mapBoard->setGeometry(QRect(10, 50, 731, 431)); mainLayout = new QVBoxLayout; //Widgets spacer = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); gameTurnWidget *gameTurn = new gameTurnWidget(&helper;, this); lstRRWidget = new QListWidget(this); gameBoardWidget *gameBoard = new gameBoardWidget(&helper;, this); //Buttons quitButton = createButton("Quit"); connect(quitButton, SIGNAL(clicked()), this, SLOT(close())); advanceTurn = createButton("Next Turn"); connect(advanceTurn, SIGNAL(clicked()), gameTurn, SLOT(nextTurn())); buttonLayout->setSpacing(3); buttonLayout->addStretch(1); messageLayout->setSpacing(3); messageLayout->addStretch(1); messageLayout->addItem(spacer); messageLayout->addWidget(gameTurn, 0, Qt::AlignCenter | Qt::AlignRight); mapBoard->addWidget(gameBoard); mapBoard->addWidget(lstRRWidget); buttonLayout->addItem(spacer); buttonLayout->addWidget(advanceTurn, 0, Qt::AlignBottom | Qt::AlignRight); buttonLayout->addWidget(quitButton, 0, Qt::AlignBottom | Qt::AlignRight); mainLayout->addLayout(messageLayout); mainLayout->addLayout(mapBoard); mainLayout->addLayout(buttonLayout); setLayout(mainLayout);
QPushButton *MainWindow::createButton(QString caption)
QPushButton *button = new QPushButton(caption, this);
When you call addWidget() or addItem() on a QLayout, the layout takes ownership of the widget and becomes responsible for deleting the item. So in your constructor, delete is being called twice on the widgets that have been added to the layouts, thus the crash.
If you remove the delete calls for the items in layouts, things should be fine.
When your QObject inherited objects are created on heap with parent, you should NOT delete it by yourselves.since QObject tree will take care of the memory memory management.
[quote author="changsheng230" date="1311043577"]When your QObject inherited objects are created on heap with parent, you should NOT delete it by yourselves.since QObject tree will take care of the memory memory management.[/quote]
It is not necessary to delete them, but it is allowed.
There are some bugs in your code:
you add the object spacer to more then 1 layout
your crash is also due to the spacer. The spacer is no widget and belongs to the layout it is added to. This means, it is deleted twice!
So use one spacer for each layout and if you don't need it later on, don't store the pointer to it.
By the way, why do you use set<Geometry for the layouts? you should not do it as it is changed after adding the layout to the global one.
Thanks for the very quick responses! I created individual spacers for the buttonLayout and the messageLayout. I also removed the the delete statements for the different widgets contained in the layouts. No more crashing on close.
I used the set Geometry to position the Message and Button layouts at the top and bottom of the screen but that was before I added the vertical box layout. I suppose that the statement is somewhat redundant now that they are contained in another layout.
Bumping an existing thread rather than starting a new one since its the same topic.
I am struggling to get my head around this for some reason, having come from Borland C++ I'm struggling with the layouts concept still. (been using QT for less than a week still)
Does this mean that objects/widgets do not require deleting, at all, if they are assigned to a layout?
When does the top layout get deleted (and in-turn delete all the other objects/widgets)? (at exit or when the tab is delete in my case?)
I have an app that creates the same class many times as needed and assigns widgets to various Tabs for display. When the tab is closed (using delete ui->tabWidget->currentWidget();) I get a seg fault and I suspect it's because of the double delete as discussed above.
Problem is, I'm not sure if my components are getting removed from memory which is a problem for me (app needs to run for weeks at a time).
Could someone direct me to a document that discusses this, or explain best practices please.
welcome to the devnet forum,
There is a lot documentation you can read. I suggest you to read a good book about Qt. there are several available. "This one gives you a good place to start.":http://www.qtrac.eu/C++-GUI-Programming-with-Qt-4-1st-ed.zip
Furthermore you can read the docs too.
"about the Qt object model":http://doc.qt.nokia.com/4.7/object.html
about the layout system
Feel free to ask specific questions about your code and please start a new topic in that case.
BTW : you are asking for sigfaults with a nickname like that ;)
Eddy, I downloaded that book just this morning and am getting ready to read it tonight!
Thanks for the extra links, Ill add them to my list of late night reading.
I searched the docs but couldn't get a reasonable description that described what I was experiencing; until I came across this thread.
Thanks for the help.
ps. The handle is actually a result of my frustration. :)
In the first chapters the authors explain it.
Have a good reading.
some general info:
The deleting is not due to layouts directly, they just do something for you, that you could also do on your own :-)
The magic here is parent/child relationship. All QObject derived classes may have a parent. All widgets have a parent unless they are top level. An QObject derived class deletes all children during it's own destruction. Now comes the layout into the game: The layout reparents the widgets so they have a parent which is responsible for the lifetime of the object.
A spacer (which is no widget) belongs to the layout, so the layout deletes it. and a layout belongs to a layout or a widget, so they are also automatically deleted.
Summary: Only delete top level items directly, or widgets, you definitely need destructed. They will destroy all child objects implicit.