c++ - 带有成员 QWidget 和 QLayout 的 QMainWindow 在退出时崩溃,如何解决?

标签 c++ qt

下面是一个单文件的QWidget程序。

//main.cpp
#include <QApplication>
#include <QMainWindow>
#include <QVBoxLayout>
#include <QLabel>
class MainWindow:public QMainWindow{
    QLabel lb;
    QWidget wgt;
    QVBoxLayout lout{&wgt};
public:
    MainWindow(){
        lout.addWidget(&lb);//line A
        setCentralWidget(&wgt);
    }
};
int main(int argc, char *argv[]){
    QApplication a(argc, argv);
    MainWindow w;
    w.show();
    return a.exec();
}

程序在退出时崩溃。崩溃时的函数调用跟踪是

system calls
QObjectPrivate::deleteChildren()
QWidget::~QWidget()
QMainWindow::~MainWindow
main

如果删除 A 行,则不会发生崩溃。

我想弄清楚导致崩溃的原因,以及如何在不崩溃的情况下使用成员 QWidget 和 QLayout。提前致谢。

最佳答案

虽然问题是由于试图释放未在堆上分配的内存,但我不认为 QMainWindow 析构函数或“双重删除” ' 是罪魁祸首(如其他地方所建议的那样)。

QObject 析构函数除了删除它的子对象外,还将把它自己从任何父对象的对象层次结构中删除。在显示的代码中,wgtMainWindow 的数据成员,这意味着 wgt 的 dtor 将在 MainWindow实例。因此,当 ~MainWindow 被调用时,wgt 不再是一个 child ,此时不会尝试释放它。所以这不是问题。

相反,真正的问题是数据成员 lbloutwgtMainWindow< 中声明的顺序类...

class MainWindow: public QMainWindow {
    QLabel      lb;
    QWidget     wgt;
    QVBoxLayout lout{&wgt};

小部件层次结构是...

wgt
  \_lb

和隐含的构造顺序...

lb
lout
wgt

意味着调用 dtor 的顺序是...

wgt
lout
lb

因此,当 wgt 析构函数被调用时,lb 仍然是一个 child ,wgt 将尝试释放它。这就是这个特定案例中问题的原因。虽然可以通过在堆上分配各种 QObject 来解决,但另一种解决方案是简单地重新排序 MainWindow 中的成员声明,​​以确保正确的顺序 build 与破坏……

class MainWindow: public QMainWindow {
    QWidget     wgt;
    QVBoxLayout lout{&wgt};
    QLabel      lb;

关于c++ - 带有成员 QWidget 和 QLayout 的 QMainWindow 在退出时崩溃,如何解决?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71882880/

相关文章:

c++ - boost interprocess file_lock不适用于多个进程

c++ - 用于自定义分辨率和同步计时的 AMD API 与 NVIDIA NVAPI 的 NDA 版本是什么等效的?

c++ - 带有 OpenCV 的伯努利矩阵

c++ - 如何在 Qt 中保存 3DSurface?

c++ - Qt 4.8 信号/插槽在 moveToThread() 之后未调用

c++ - 在 QT 中解析 JSON 对象中的 JSON 对象

c++ - 我应该使用全局变量还是每次都调用该函数? C++

c++ - 无法在 C++ 中写入文件

javascript - 如何将组件定位在我所有 QML View 的顶部

c++ - 如何用QTest测试QTableView版本?