调用member->函数(this);在析构函数中导致Segfault

时间:2016-06-11 05:46:18

标签: 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 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 :: add / removeIconWorking(IconWorking *)不对对象本身做任何事情;他们只是从QList中添加/删除它。与Qt的原生对象系统类似,除了我想保证只有IconWorking在那里进行一些特殊的处理。

我错过了什么?

更新

我根据评论添加了一些测试代码,以查看parentPage是否发生了变化。它没有。我正在使用一个新创建的变量,该变量在构造函数中分配并在析构函数中签入。

段错误消息未指定地址。如果它做的话会很好。直接检查指针会给出原始和添加的测试的非零值,因此它们不为空。

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

2 个答案:

答案 0 :(得分:2)

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

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

    ~FullPage()实例上调用
  1. parentPage。之后,parentPage不再是有效的FullPage对象!
  2. 调用
  3. ~Widget(),留下QObject。
  4. 调用
  5. ~QObject(),删除您的IconWorking对象(因为父子关系)
  6. 执行
  7. ~IconWorking(),在parentPage上调用FullPage :: removeIconWorking(),我假设它访问已在步骤1中销毁的FullPage特定成员。(对象parentPage仅指向此点)一个有效的QObject,没别的!)
  8. 崩溃
  9. 要使此方法有效,~TullPage()必须手动删除IconWorking对象,而不是依赖于QObject父子关系。

答案 1 :(得分:0)

好吧,我发现项目的另一部分本来就很难用这个结构,所以我:

  • 制作FullPage的QList public
  • 取消添加和删除的成员函数。
  • IconWorking直接操纵它,因为无论如何都会发生这种情况。

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

所以我猜这个故事的寓意是,如果它做了一些奇怪的事情,试试一个完整的重建。一个类的更改可能需要重新编译另一个类,即使其他源实际上没有更改,Qt Creator也不一定知道。