【问题标题】:Qt destructor call for closed widgetQt析构函数调用关闭的小部件
【发布时间】:2011-10-28 20:12:21
【问题描述】:

有处理文本命令的应用程序。我有一个用一些close * 命令关闭的Qt 小部件。 Qt::WA_DeleteOnClose 为该小部件设置了属性,它接收 closeEvent,但稍后调用该对象的析构函数(我猜是空闲时)。如果我有两个命令 close *; get something; 程序崩溃,因为 get something 在该小部件的析构函数之前被调用,因此它尝试访问由 close * 命令删除的数据。如何强制 Qt 调用析构函数? QCoreApplication::processEvents() 关闭命令后没有帮助。 将 qt 版本从 4.3.3 更改为 4.7.2 后,我遇到了这个问题。这里没有多线程。

提前致谢。

添加

这是代码示例。

test *t = new test();
t->show();
std::cout << "before deleteLater()" << std::endl;
t->deleteLater();
std::cout << "after deleteLater()" << std::endl;
QCoreApplication::sendPostedEvents();
QCoreApplication::processEvents();
std::cout << "after processEvents()" << std::endl;

测试类是从 QDialog 派生的。它在构造函数中打印test(),在析构函数中打印~test()。此代码给出以下输出

test()
before deleteLater()
after deleteLater()
after processEvents()
~test()

根据 Qt 文档,它应该在最后一个 cout 之前删除对象,对吗?看起来像Qt中的一个错误,有人知道吗?有什么解决方法吗?

我在 Qt 邮件列表中提出了问题,但仍在等待答案。

谢谢。

另一个更新

这段代码

Dialog::~Dialog() {
    std::cout << "~test()" << std::endl;
}

int main(int argc, char* argv[]) {
    QApplication app(argc, argv);
    Dialog* dlg = new Dialog();
    dlg->setAttribute(Qt::WA_DeleteOnClose);
    dlg->show();
    dlg->close();
    std::cout << "before sendPostedEvents()" << std::endl;
    QCoreApplication::sendPostedEvents();
    std::cout << "after sendPostedEvents()" << std::endl;
    return app.exec();
}

打印这个

before sendPostedEvents()
after sendPostedEvents()
~test()

但只要我添加 closeEvent 处理程序并在该处理程序函数中调用 deleteLater(),sendPostedEvents 就会开始删除延迟对象。

void Dialog::closeEvent(QCloseEvent* ev) {
    deleteLater();
    QWidget::closeEvent(ev);
}

打印这个 在 sendPostedEvents() 之前 〜测试() 在 sendPostedEvents() 之后

谁能解释一下到底发生了什么?这只是一个错误吗?我可以使用它作为解决方法吗?

这是如何工作的?如果设置了 CloseOnDelete 属性,Qt 不应该在接受 closeEvent 之后自动调用 deleteLater() 吗?

【问题讨论】:

  • 拜托,如果您能找到解决方案,您能否在此处提供一些更新。我有同样的问题,我真的很好奇它是如何解决的。

标签: c++ qt memory-management destructor


【解决方案1】:

设置Qt::WA_DeleteOnClose意味着qt可以在你调用close()后随时删除,因为qt内部使用deleteLater()。您可以使用QObject::destroyed() 信号确保删除。

【讨论】:

  • 我可以通过在 closeEvent 函数中为该小部件添加 deleteLater() 函数调用来修复它。但我想了解解决方案。您能否更详细地解释一下或提供解释该技术的链接?
  • 我想确保 Qt 在我执行完第一个命令时删除 。我怎样才能做到?
  • 如果你可以关闭它,你也可以删除它。不要设置Qt::WA_DeleteOnClose 标志并简单地删除它。到时候你就确定了。
  • 应用程序真的很大,那么我需要确保从调用 close 的任何地方删除它。我不想在那里做太多的改变。这可能会导致内存泄漏。是不是可以强制 Qt 删除标记为 DeleteOnClose 的对象?
  • 根据qt文档,你也可以使用sendPostedEvents()。 doc.qt.nokia.com/latest/qcoreapplication.html#processEvents
【解决方案2】:

QCoreApplication::processEvents 明确跳过关闭事件的删除。您需要将 QEventLoop::DeferredDeletion 传递给 processEvents()。即 QCoreApplication::processEvents(QEventLoop::DeferredDeletion);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-06-20
    • 1970-01-01
    • 1970-01-01
    • 2013-04-04
    • 1970-01-01
    • 2014-05-18
    • 2018-12-09
    相关资源
    最近更新 更多