C++ 呼叫成员->;功能(本);在析构函数中导致Segfault
以下是违规代码:C++ 呼叫成员->;功能(本);在析构函数中导致Segfault,c++,qt,segmentation-fault,destructor,C++,Qt,Segmentation Fault,Destructor,以下是违规代码: class FullPage : public QWidget { Q_OBJECT public: explicit FullPage(const AppData* appdata, QWidget* parent = 0); virtual void addIconWorking(IconWorking* temp); virtual void removeIconWorking(IconWorking* temp); ..
class FullPage : public QWidget
{
Q_OBJECT
public:
explicit FullPage(const AppData* appdata, QWidget* parent = 0);
virtual void addIconWorking(IconWorking* temp);
virtual void removeIconWorking(IconWorking* temp);
...
}
class IconWorking : public QLabel
{
Q_OBJECT
public:
explicit IconWorking(FullPage* parent = 0);
virtual ~IconWorking();
...
}
IconWorking::IconWorking(FullPage* parent) : QLabel(parent)
{
...
parentPage = parent;
parentPage->addIconWorking(this);
...
}
IconWorking::~IconWorking()
{
parentPage->removeIconWorking(this); //segfault
QMessageBox::information(0, "TODO", "Reminder Message");
}
- 标记的线路在呼叫前出现故障。(断点已命中,但函数中的断点未命中)
- parentPage永远不会被删除,此时具有非零值
- 添加/删除图标工作(IconWorking*)不要对对象本身做任何事情;他们只是从QList中添加/删除它。类似于Qt的本机对象系统,只是我想保证只有IconWorking的在那里进行一些特殊处理
更新: 我在注释中添加了一些测试代码,以查看parentPage是否发生过更改。没有。我正在使用一个新创建的变量,该变量在构造函数中赋值,并在析构函数中签入 SEGFULT消息未指定地址。如果是的话,那就太好了。直接检查指针会给出一个非零值,包括原始测试和添加的测试,因此它们不是null
我还发现,当我添加一些功能时,我在一个完全不相关的位置得到了一个新的segfault,它引用了在程序中以参数形式传递的同一个完整页面实例。假设在父页面被破坏时调用了
~IconWorking()
,正如亲子关系所表明的那样:
当parentPage对象被销毁时,事情按以下顺序发生:
parentPage
实例上调用~FullPage()
。在此之后,parentPage不再是有效的FullPage对象李>
~Widget()
,留下一个QObject~QObject()
,删除IconWorking对象(由于父子关系)~IconWorking()
,调用父页面上的FullPage::removeIconWorking(),我假设它访问已在步骤1中销毁的特定于FullPage的成员。(此时,parentPage指向的对象仅为有效的QObject,没有其他内容!)要使此方法起作用,~FullPage()必须手动删除IconWorking对象,而不是依赖QObject父子关系。好吧,我发现项目的另一部分可能会对该结构感到尴尬,因此我:
- 使完整页面的QList
公开
- 删除了要添加和删除的成员函数
- 让我直接操纵它,因为这就是所有发生的事情
所以我猜这个故事的寓意是,如果它做了一些奇怪的事情,尝试一次彻底的重建。一个类中的更改可能需要重新编译另一个类,即使另一个源实际上没有更改,Qt Creator也不一定知道这一点。现在看不到任何问题。
parentPage
的值仍然有效吗?segfault提到了哪个地址(如0与其他地址)removeConworking
是虚拟的,这表明此
指向无效位置,并且当程序尝试取消引用指针以访问vtable时,会发生segfault。检查parentPage是否不为null。在ctor中打印parentPage
和*parentPage
,然后再次在dtor中,验证parentPage
未更改且*parentPage
仍然合理。您如何调用析构函数?通过删除其父项或删除IconWorking
?我想我应该更清楚。有几个完整的页面在整个应用程序关闭之前是不会被销毁的。I与这些父对象一起创建工作,然后在父对象存活期间随意删除,让析构函数负责清理。@AaronD:然后请添加一个回溯以查看在哪种上下文中调用数据或等待一分钟……事实上,我认为您做得对。就是在我关闭应用程序的时候,这完全符合你所描述的。这是正常使用的例外,我只是碰巧测试了一下+1.