【问题标题】:Qt double free or corruptionQt 双重释放或损坏
【发布时间】:2016-07-12 09:20:10
【问题描述】:

我开发了一个 Qt 应用程序,它有一个身份验证小部件和一个主窗口。身份验证成功后,我使用此代码打开 mainWindow

this->~Authentification();
MainWindow *w = new MainWindow(); 

但在我关闭主窗口后,我收到双重释放或损坏错误。调试说这个错误的来源是

delete ui;

来自班级Authentification

【问题讨论】:

  • 身份验证是否会从 QObject 中删除?在技​​术上可行的情况下从类中调用析构函数也很棘手,如果出现错误(您必须保证以后不会触及它)。如果 Authentification IS QObject 那么我建议使用 this->deleteLater();另外,您没有将 MainWindow 传递给父级,并且由于您在现在已销毁的类中调用 new ,因此您会泄漏内存,因为您不可能获得删除它的指针。如果你在那个电话之后显示它然后删除它......你仍然在被破坏的类中操作。看起来是非常糟糕的设计决定。
  • 永远不要显式调用析构函数。除了很少见的“安置新”。
  • 是的 Authentification 是一个 QWidget 并且来自 QObject。问题是当我调用 this->~Authentification(); 时。身份验证类没有完全关闭,当我关闭主窗口时,它还会再次调用 ~Authentification()。
  • @Dababi 永远不要在 QObjects 上调用 delete,也永远不要直接调用它们的析构函数。哦,天哪,你为什么要从内部这样做?!我的意思是 Qt 具有超级微调和简单的内存管理系统,那么你为什么还要尝试这个呢?如果必须,至少使用 deleteLater()。另外,如果周围没有合适的父级或者您无法将其放入堆栈,您可以在其关闭信号上将 MainWindow 连接(连接)到其 deleteLater 插槽。
  • 感谢@Resurrection,当我删除这个时->~Authentification();问题消失了,但我需要关闭身份验证窗口。最好的方法是什么。

标签: qt


【解决方案1】:

您在this 上显式调用析构函数。很少有时候你需要这样做,而且它们总是应该被抽象出来。此类调用仅属于低级资源管理类。如果你想在 QObjectQWidget 的子类中这样做,你很可能不应该这样做!

如果您只想关闭一个窗口,请使用QWidget::close()。但也许您也希望销毁小部件实例,以释放它使用的任何资源。然后继续阅读。

假设Authentication 是一个适当的对话框,在身份验证成功或失败时分别发出accepted()rejected() 信号:

class Authentication : public QDialog {
  ...
};

从此类对话中继续进行的一些方法可能是:

  1. 将对话框定义为作用域的局部变量,只要对话框处于活动状态,就运行事件循环,然后离开作用域:

    int main(int argc, char ** argv) {
      QApplication app{argc, argv};
      {
        Authentication auth;
        auto result = auth.exec();
        if (result == QDialog::Rejected) return 1;
      } // here auth has been destructed
      MainWindow window;
      window.show();
      return app.exec();
    }  
    
  2. 动态分配对话框,并在关闭时自动删除。

    int main(int argc, char ** argv) {
      QApplication app{argc, argv};
      auto auth = new Authentication;
      auth->setAttribute(Qt::WA_DeleteOnClose);
      QObject::connect(auth, &QDialog::accepted, []{
        auto win = new MainWindow;
        win->setAttribute(Qt::WA_DeleteOnClose);
        win->show();
      });
      auth->show();
      return app.exec();
    }
    

【讨论】:

    猜你喜欢
    • 2023-03-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多