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

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

这是有问题的代码:

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 是否发生过更改。它没有。我正在使用在构造函数中分配并在析构函数中检查的新创建的变量。

段错误消息未指定地址。如果它这样做会很好。直接检查指针给出了一个非零值,包括原始和添加的测试,所以它们不是空的。

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

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

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

  1. ~FullPage()parentPage 实例上调用。之后,parentPage 不再是有效的 FullPage 对象!
  2. ~Widget()被调用,留下一个QObject。
  3. ~QObject() 被调用,它删除了你的 IconWorking 对象(因为父子关系)
  4. ~IconWorking() 被执行,它在 parentPage 上调用 FullPage::removeIconWorking(),我假设,它访问已在步骤 1 中销毁的 FullPage-specific 成员。(parentPage 指向的对象位于这一点只有一个有效的QObject,没有别的!)
  5. 崩溃

要使这种方法起作用,~FullPage() 必须手动删除 IconWorking 对象,而不是依赖于 QObject 父子关系。

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

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

不知何故,这似乎修复了析构函数中的段错误,但我在某些 class 定义本身上得到了它们。 (什么!?!)所以我重建了项目,这也被修复了。


所以我想这个故事的寓意是,如果它做了一些奇怪的事情,请尝试完全重建。一个 class 中的更改可能需要重新编译另一个,即使另一个源实际上没有更改,Qt Creator 不一定知道这一点。