【问题标题】:Memory-Management in Qt: AddressBook tutorialQt 中的内存管理:地址簿教程
【发布时间】:2014-06-05 10:02:19
【问题描述】:

到目前为止,我已经了解到,当父对象被删除时,Qt 会释放所有子对象的内存。此外,通常不必关心堆栈上创建的对象的内存管理(即不作为指针)。

现在,当我做得很好 "AddressBook" tutorial 时,我在第 5 部分中发现了这一点:

AddressBook::AddressBook(QWidget *parent) : QWidget(parent)
{
    dialog = new FindDialog;
}

提供完整的源代码: addressbook.h addressbook.cpp finddialog.h

这里,dialog 是AddressBook 的私有成员,它是一个指向FindDialog 的指针。 FindDialog 继承 QDialog,但没有 this-Pointer 传递给构造函数(如上所示)。不存在显式析构函数,不存在delete dialog-call...

另外,不传递this 似乎是故意的:

[FindDialog's] 构造函数被定义为接受父 QWidget,即使对话框将作为单独的窗口打开。

这不会导致内存泄漏吗?或者是否有其他机制可以静默删除dialog 并释放其内存?

提前感谢您的帮助!

更新:我将此问题发布到qt-project.org forums,它应该很快就会得到修复。

【问题讨论】:

  • 不错。这几乎可以肯定是内存泄漏,除非Q_OBJECT 宏发生了一些真正的魔法。您可以使用valgrind 确定地验证这一点。但是,这无关紧要,因为AddressBook 会持续应用程序的生命周期。不过,在教程中,它应该被释放,正是为了避免引起像你这样的问题。
  • @MattPhillips 但是AddressBook 仅持续应用程序的生命周期不会影响dialog,是吗?它会,如果它是在堆栈上创建的,但在这种情况下不是......
  • 重点是,AddressBook 实例仅在应用程序终止时被销毁,此时与其关联的所有内存(包括dialog)都被释放。因此避免了内存泄漏,但以一种风格不佳且不可扩展的方式。
  • 就我而言,该成员应声明如下:FindDialog dialog。然后你不需要显式分配或构造它,它不会泄漏。完全没有理由在这里使用指针。
  • @Massa:这当然是可能的,但或许应该对此发表评论。指针的使用仍然是一个不必要的复杂性。

标签: c++ qt qwidget qtgui qdialog


【解决方案1】:

这没有任何借口,它最终会带来比你刚刚提出的更多的问题,即:

  • 不像你说的那样管理。

  • 它不使用传统的 new Foo() 语法。

  • 没有在构造函数的初始化列表中完成。

一旦应用程序退出,操作系统可能会释放它,但无论如何,我总是反对这些问题,尤其是在示例项目中。在我看来,适当的解决方法是使用堆栈对象而不是堆对象或QPointer。

如果是后者,请参阅以下帖子:

How to crash (almost) every Qt/KDE Application and how to fix

这应该在上游报告并修复;好收获!

我刚刚向 Gerrit 提交了关于此 in here 的更改。

【讨论】:

  • 感谢您提供的信息和博客条目的链接.. 非常有趣!我刚刚在 qt-project.org-Forum 上发帖建议解决这个问题。
  • 关于new Foo 与new Foo() 语法要点的附加说明:由于Dialog 是一种非POD 类型,它们的作用完全相同,但使用() 仍然是一个好习惯。更多关于它的信息,例如here。
  • @hyde:即使是非 POD 类型也属于 C++03 及更高版本的 non-initialized vs. default/value initialized difference。它们在 C++98 中同样未初始化,因此它也将取决于标准变体。但正如更新所写,现在有一个更改提交给 Gerrit,这使得对象堆栈而不是堆。
猜你喜欢
  • 2011-04-30
  • 2011-01-30
  • 1970-01-01
  • 2023-03-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-27
相关资源
最近更新 更多