July 19, 2011

cazador7907 cazador7907
Lab Rat
78 posts

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.

  1. #include "mainwindow.h"
  2.  
  3. MainWindow::MainWindow()
  4. {
  5.     setMinimumSize(600, 400);
  6.     setMaximumSize(1000, 800);
  7.     resize(752,533);
  8.  
  9.     setWindowTitle("Two Button Test");
  10.  
  11.     messageLayout = new QHBoxLayout;
  12.     messageLayout->setGeometry(QRect(10, 10, 731, 31));
  13.  
  14.     buttonLayout = new QHBoxLayout;
  15.     buttonLayout->setGeometry(QRect(10, 489, 731, 41));
  16.  
  17.     mapBoard = new QHBoxLayout;
  18.     mapBoard->setGeometry(QRect(10, 50, 731, 431));
  19.  
  20.     mainLayout = new QVBoxLayout;
  21.  
  22.     //Widgets
  23.     spacer = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
  24.  
  25.     gameTurnWidget *gameTurn = new gameTurnWidget(&helper;, this);
  26.     lstRRWidget = new QListWidget(this);
  27.     gameBoardWidget *gameBoard = new gameBoardWidget(&helper;, this);
  28.  
  29.     //Buttons
  30.     quitButton = createButton("Quit");
  31.     connect(quitButton, SIGNAL(clicked()), this, SLOT(close()));
  32.  
  33.     advanceTurn = createButton("Next Turn");
  34.     connect(advanceTurn, SIGNAL(clicked()), gameTurn, SLOT(nextTurn()));
  35.  
  36.     buttonLayout->setSpacing(3);
  37.     buttonLayout->addStretch(1);
  38.  
  39.  
  40.     messageLayout->setSpacing(3);
  41.     messageLayout->addStretch(1);
  42.     messageLayout->addItem(spacer);
  43.     messageLayout->addWidget(gameTurn, 0, Qt::AlignCenter | Qt::AlignRight);
  44.  
  45.     mapBoard->addWidget(gameBoard);
  46.     mapBoard->addWidget(lstRRWidget);
  47.  
  48.     buttonLayout->addItem(spacer);
  49.     buttonLayout->addWidget(advanceTurn, 0, Qt::AlignBottom | Qt::AlignRight);
  50.     buttonLayout->addWidget(quitButton, 0, Qt::AlignBottom | Qt::AlignRight);
  51.  
  52.     mainLayout->addLayout(messageLayout);
  53.     mainLayout->addLayout(mapBoard);
  54.     mainLayout->addLayout(buttonLayout);
  55.  
  56.     setLayout(mainLayout);
  57.  
  58. }
  59.  
  60. MainWindow::~MainWindow()
  61. {
  62.     delete quitButton;
  63.     delete advanceTurn;
  64.     delete lstRRWidget;
  65.     delete spacer;
  66.     delete buttonLayout;
  67.     delete messageLayout;
  68.     delete mainLayout;
  69.  
  70. }
  71.  
  72. QPushButton *MainWindow::createButton(QString caption)
  73. {
  74.     QPushButton *button = new QPushButton(caption, this);
  75.     button->setFlat(true);
  76.  
  77.     return button;
  78. }

 Signature 

Laurence -

 

9 replies

July 19, 2011

mlong mlong
Robot Herder
1551 posts

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.

 Signature 

Senior Software Engineer
AccuWeather Enterprise Solutions
/* My views and opinions do not necessarily reflect those of my employer.  Void where prohibited. */

July 19, 2011

changsheng230 changsheng230
Lab Rat
128 posts

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.

 Signature 

Chang Sheng
常升

July 19, 2011

Gerolf Gerolf
Robot Herder
3287 posts
changsheng230 wrote:
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.

It is not necessary to delete them, but it is allowed.

There are some bugs in your code:

  1. you add the object spacer to more then 1 layout
  2. 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.

 Signature 

Nokia Certified Qt Specialist.
Programming Is Like Sex: One mistake and you have to support it for the rest of your life. (Michael Sinz)

July 19, 2011

cazador7907 cazador7907
Lab Rat
78 posts

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.

 Signature 

Laurence -

 

July 27, 2011

seg_fault seg_fault
Lab Rat
19 posts

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.

Thanks!

July 27, 2011

Eddy Eddy
Area 51 Engineer
1612 posts

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. [qtrac.eu]

Furthermore you can read the docs too.
about the Qt object model [doc.qt.nokia.com]

about the layout system
http://doc.qt.nokia.com/4.7/widgets-and-layouts.html
http://doc.qt.nokia.com/4.7/layout.html

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 ;)

 Signature 

Moderator
Qt Certified Specialist
Nokia Qt Ambassador

July 27, 2011

seg_fault seg_fault
Lab Rat
19 posts

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. :)

July 27, 2011

Eddy Eddy
Area 51 Engineer
1612 posts

Hi,

In the first chapters the authors explain it.
Have a good reading.

 Signature 

Moderator
Qt Certified Specialist
Nokia Qt Ambassador

July 27, 2011

Gerolf Gerolf
Robot Herder
3287 posts

Hi seg_fault,

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.

 Signature 

Nokia Certified Qt Specialist.
Programming Is Like Sex: One mistake and you have to support it for the rest of your life. (Michael Sinz)

 
  ‹‹ QStandardItem subclassing?      Table data into XML file format ››

You must log in to post a reply. Not a member yet? Register here!