Antonio Del Sannio
Antonio Del Sannio

Reputation: 315

Opening a new QMainWindow crash after destructor

A first MainWindow is open in the main ,then when I try to open a second window the program crashes with a SIGABRT . The debugger shows the following lines:

double free or corruption (out): 0x00007fffffffe340 ***

RTTI symbol not found for class 'QObject'
RTTI symbol not found for class 'QObject'
RTTI symbol not found for class 'QObject'
RTTI symbol not found for class 'QObject'
RTTI symbol not found for class 'QObject'
RTTI symbol not found for class 'QObject'
RTTI symbol not found for class 'QObject'

I want to understand what's the right way to call the destructor , if I do not set the Qt::WA_DeleteOnClose attribute the program works and if I do the same in the second window ,(I.E i open a third window in the second QMainwindow) the program works even if i set the Qt::WA_DeleteOnClose attribute.Why I can't do that only in the first QMainWindow ?The one I open in the main?

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    this->setAttribute(Qt::WA_DeleteOnClose);
    QTimer *t = new QTimer(this);
    connect(t,SIGNAL(timeout()),this,SLOT(open_new()));
    t->start(1000);
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::open_new(){
    MainWindow2 *win_2 = new MainWindow2(0);
    win_2->show();
    this->close();
}

Upvotes: 3

Views: 1278

Answers (1)

Matt
Matt

Reputation: 15081

In Qt all QWidgets are managed like this:

  1. All destructors are virtual.
  2. If a widget (well, in fact, any QObject) has a parent, then the parent deletes it (using operator delete) himself. That is, all child widgets must be created by the operator new, or must be destructed before the parent is (see @BenjaminT comment).
  3. If a widget has no parent (i.e. 0) and has the attribute WA_DeleteOnClose set, then it initiates the call of the operator delete himself (by using a member function deleteLater(), see @BenjaminT comment), while processing the close signal (the actual delete gets called, well, later, i.e. not inside the slot code, see @DmitrySazonov comment). Again, (a) an application should not do this itself, because it's redundant; (b) a widget still should be created with the operator new.
  4. If a widget has no parent, and has no WA_DeleteOnClose attribute set, then it's up to the calling application how to create and destruct it. For example, if QWidget is a stack variable, then it gets destructed automatically when returning from the corresponding function (as it's normal in C++).

In your case, the first MainWindow wasn't probably created with the new operator, so it mustn't have WA_DeleteOnClose attribute set. But the following code should work OK:

int main(int argc, char* argv[])
{
    QApplication app(argc, argv);
    MainWindow* w = new MainWindow(0);
    // redundant if the attibute is set inside the class constructor
    //w->setAttribute(Qt::WA_DeleteOnClose);
    w->show();
    return app.exec();
}

Upvotes: 7

Related Questions