删除QWidget类型的静态类实例会导致无效的指针错误

问题描述 投票:0回答:2

我试图通过对QWidget进行子类化并导出静态类实例来创建单例类。但是,尝试删除此类实例会导致崩溃。为什么?

#include <QWidget>
#include <QApplication>

using namespace std;

class MyWidget : public QWidget
{
  public:
    static MyWidget *get_instance(){ static MyWidget instance; return &instance; };
};



int main
(
  int argc,
  char **argv
)
{
    QApplication app( argc, argv );
    MyWidget *widget = MyWidget::get_instance();

    QWidget *parent_widget = new QWidget;
    widget->setParent( parent_widget );
    delete parent_widget; //crashes 

    return app.exec();
}

运行上面的代码会产生以下错误消息。我没有包含bakctrace消息,该消息太长而无法在此帖子中显示。

QStandardPaths: XDG_RUNTIME_DIR not set, defaulting to '/tmp/runtime-jon'
QStandardPaths: XDG_RUNTIME_DIR not set, defaulting to '/tmp/runtime-jon'
*** Error in `/home/shouheng/tmp/build-exp_main-Desktop_Qt_5_10_0_GCC_64bit-Debug/exp_main': free(): invalid pointer: 0x00000000006030c0 ***
c++ qt static qt5
2个回答
3
投票

[删除父窗口小部件时,将在其所有子窗口上调用delete,从而在您未使用new创建的单例对象的指针上被调用,即未分配在堆上:

static MyWidget instance; 

为了避免这种情况,只需un-parent这样的单例对象

widget->setParent(nullptr);

在调用parent_widget上的删除之前。


2
投票

Qt与父母的所有权转移/处理所有权。

所以当你这样做

widget->setParent( parent_widget );

[parent_widget将删除其析构函数中的widget(除非其父级之前已更改)。

© www.soinside.com 2019 - 2024. All rights reserved.