开发者

Why is this QT app exiting with a SIGABRT signal?

I'm new to Qt. So I started to reimplement one of the get started examples: link.

However I get a SIGABRT signal when closing the windows. The reason for this is obvoisly due to some memory managment error.

Below you find the callstack and the relevant code. The line editWindow.setLayout(&layout); causes the error. Is the layout class deleting widgets on destruction, therefor claiming ownership of them?

Whats the reaon for this behavior? And how to fix it?

Best regards.

information

callstack

Why is this QT app exiting with a SIGABRT signal?

source

  QPushButton testButton("Test")开发者_如何学编程;

  QVBoxLayout layout;
  layout.addWidget(&testButton);

  QWidget editWindow;
  // the following line is the source of the error
  editWindow.setLayout(&layout);
  editWindow.show();

  int val = app.exec();


Many different Qt functions will take ownership of the object being passed in which means it assumes control over all memory management and will free it upon delete. From the setLayout docs:

The QWidget will take ownership of layout.

After you have called setLayout it has a parent and its parent deletes it in addition to it being deleted when the method's stack is cleaned up. Thus, it's being deleted twice which is causing the problems.

If everything else is correct, this change should fix it:

QVBoxLayout *layout = new QVBoxLayout();
//...
layout->addWidget(&testButton);
//...
editWindow.setLayout(layout);

Also, note that it's typical to create the main widget and then assign widgets that will be displayed on that widget as the parent. In other words, I'd expect something more like the following (though not strictly necessary). This also helps assure that if something does get reparented in the future you won't have problems:

QWidget editWindow;
QVBoxLayout *layout = new QVBoxLayout();
QPushButton *testButton = new QPushButton(&editWindow);
layout->addWidget(testButton);
editWindow.setLayout(layout);
editWindow.show();
int val = app.exec();

Most Qt objects which are reparented and to which ownership changes may happen will have a constructor that accepts a QWidget* or QObject*.


QWidget expects a layout instance created via operator new and takes ownership of the instance, calling delete on it when the QWidget is destroyed (see documentation). Hence what you need is something like this:

QVBoxLayout *layout = new QVBoxLayout();
/// ...
editWindow.setLayout(layout);

The same thing with ownership applies to your testButton.


The example code seems to be wrong (oddly enough). The destructor of a QWidget calls delete on its layout. In your case, the QVBoxLayout instance has been created on the stack rather than the heap, so calling delete on that pointer is invalid is aborts the application.

Same goes for all children of a QObject. When a QObject gets deleted, it calls delete on all of its children, and if those children have been created on the stack, it will fail in the same way.

Now, to understand why Nokia posted such a bad example...

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜