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

Opening a new QMainWindow crash after destructor

第一个 MainWindow 在主窗口中打开,然后当我尝试打开第二个时 window 程序因 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 属性,程序就可以运行,并且 如果我在第二个 window 中做同样的事情,(即我在第二个 QMainwindow 中打开第三个 window)即使我设置 Qt::WA_DeleteOnClose attribute.Why 我不能只在第一个 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();
}

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

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

在您的情况下,第一个 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();
}