在析构函数后打开一个新的QMainWindow崩溃

时间:2017-11-02 10:25:04

标签: c++ qt destructor qmainwindow

第一个MainWindow在main中打开,然后当我尝试打开第二个时 窗口程序崩溃了SIGABRT。 调试器显示以下行:

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'

我想了解调用析构函数的正确方法, 如果我没有设置Qt :: WA_DeleteOnClose属性,程序可以工作 如果我在第二个窗口中执行相同的操作(IE我在第二个QMainwindow中打开第三个窗口),即使我设置了Qt :: WA_DeleteOnClose属性,该程序也能正常工作。为什么我只能在第一个QMainWindow中执行此操作?我在主打开的那个?

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

1 个答案:

答案 0 :(得分:5)

在Qt中,所有QWidgets都是这样管理的:

  1. 所有析构函数都是虚拟的。
  2. 如果一个小部件(实际上,任何QObject)都有一个父级,那么父级将自己删除它(使用operator delete)。也就是说,所有子窗口小部件必须由operator new创建,或者必须在父窗口之前被销毁(参见@BenjaminT评论)。
  3. 如果一个小部件没有父级(即0)并且设置了属性WA_DeleteOnClose,那么它会启动operator delete自己的调用(通过使用成员函数deleteLater(),请参阅@BenjaminT注释) ,同时处理close信号(实际delete被调用,稍后,即不在插槽代码内,请参阅@DmitrySazonov评论)。同样,(a)申请本身不应该这样做,因为它是多余的; (b)仍应使用operator new创建小部件。
  4. 如果窗口小部件没有父窗口,并且没有设置WA_DeleteOnClose属性,则由调用应用程序决定如何创建和销毁它。例如,如果QWidget是一个堆栈变量,那么当从相应的函数返回时它会自动被破坏(因为它在C ++中是正常的)。
  5. 在您的情况下,第一个MainWindow可能不是使用new operator创建的,因此它不能设置WA_DeleteOnClose属性。但是下面的代码应该可以正常工作:

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