【发布时间】:2026-01-25 13:10:01
【问题描述】:
我试图通过子类化 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 ***
【问题讨论】:
-
我不确定你为什么对此感到困惑。当您调用
delete parent_widget时,parent_widget将递归删除其所有子代,依此类推。但是MyWidget::get_instance()返回的小部件不是使用new分配的——因此出现了错误。 -
在删除 qobject 时使用 qt 方式:
parent_widget->deleteLater()而不是delete parent_widget -
@tunglt 这不会解决问题,因为它仍然会尝试
delete一个未在堆上分配的对象new。 -
@tunglt 这只会将问题推迟到以后,更准确地说是when the event loop has started,但随后会出现完全相同的问题!