调用成员>函数(this);在析构函数中导致隔离错误

Calling member->function(this); in Destructor causes Segfault

本文关键字:析构函数 错误 隔离 this 成员 gt 函数 调用      更新时间:2023-10-16

以下是有问题的代码:

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");
}
  • 在调用之前标记的行segfault。(断点已命中,但函数内部的断点未命中)
  • parentPage从未被删除,并且此时具有非零值
  • FullPage::add/removeIconWorking(IconWorking*)不对对象本身执行任何操作;他们只是简单地从QList中添加/删除它。类似于Qt的原生对象系统,只是我想保证只有IconWorking在其中进行一些特殊处理

我缺少什么?


更新:

我根据注释添加了一些测试代码,看看parentPage是否会更改。事实并非如此。我使用的是一个新创建的变量,它在构造函数中赋值,并在析构函数中签入。

segfault消息没有指定地址。如果真的这样就好了。直接检查指针会得到一个非零值,包括原始测试和添加的测试,因此它们不为null。

我还发现,当我添加一些功能时,我会在一个完全不相关的位置获得一个新的segfault,它引用了程序中所有参数中传递的同一个FullPage实例。

假设~IconWorking()在其parentPage被破坏时被调用,如父子关系所示:

当parentPage对象被销毁时,事情按以下顺序发生:

  1. ~FullPage()parentPage实例上被调用。在那之后,parentPage就不再是一个有效的FullPage对象了
  2. 调用~Widget(),留下一个QObject
  3. 调用~QObject(),它会删除您的IconWorking对象(因为父子关系)
  4. 执行~IconWorking(),它调用parentPage上的FullPage::removeIconWorking(),我认为它访问在步骤1中已经销毁的FullPage特定成员。(parentPage指向的对象目前只是一个有效的QObject,没有其他对象!)
  5. Crash

为了使这种方法有效,~FullPage()必须手动删除IconWorking对象,而不是依赖于QObject父子关系。

好吧,我发现项目的另一个部分使用这种结构会很尴尬,所以我:

  • 制作FullPage的QListpublic
  • 取消了要添加和删除的成员函数
  • 让IconWorking直接操作它,因为这就是所有发生的事情

不知怎么的,这似乎修复了析构函数中的segfault,但我在一些类定义中得到了它们。(什么!?!)所以我重建了这个项目,这个问题也得到了解决。


所以我想这个故事的寓意是,如果它在做一些奇怪的事情,试着彻底重建。一个类中的更改可能需要重新编译另一个类,即使其他源实际上没有更改,QtCreator也不一定知道这一点。