繁体   English   中英

Qt5内存泄漏? 如何删除QMimeData?

[英]Memory leak in Qt5? How to get QMimeData deleted?

我刚刚提供了这个问题的答案,并且想要提供一个工作示例,当我注意到QListModel::mimeData()返回的新创建的QMimeData实例在应用程序终止之前不会被删除。

所以这不是一个真正的内存泄漏,因为Qt在关机时处理所有QMimeData实例,但你只需要拖放足够长的时间并将正确的内容放入你的mime数据中以让内存运行满。

我错过了什么? 有没有办法告诉Qt一旦不再需要它们就立即删除QMimeData实例?

请注意:

我知道QMimeData每个实例都会在程序终止时被Qt自动删除。 我的问题不是valgrindcppcheck报告的真正的内存泄漏,但看起来多个且可能非常大的QMimeData实例在运行时没有被清理,这也会耗尽内存消耗。

示例代码:

#include <QtWidgets>
#include <iostream>

struct TrackedMimeData : public QMimeData {
   TrackedMimeData(const QString & text) {
      std::cout << this << std::endl;
      setText(text);
   }
   ~TrackedMimeData() {
       std::cout << "~" << this << std::endl;
   }
};

struct MyListWidget : QListWidget {
   MyListWidget() {
      setDragEnabled(true);
      addItem("item1");
      addItem("item2");
   }
   QMimeData * mimeData(const QList<QListWidgetItem *>) const override {
      return new TrackedMimeData("hello");
   }
};

int main(int argsc, char *argsv[]) {
   QApplication application(argsc, argsv);
   MyListWidget gui;
   gui.show();
   return application.exec();
}

示例输出如下所示:

0xa58750
0xa4e0f0
~0xa4e0f0
0xa3c6c0
~0xa3c6c0
0xa51880
0xa5ecd0
0xa31f50
0xa57db0
0xa5afc0
~0xa5afc0
0xa5aa70
~0xa5aa70
------ CLOSE WINDOW
~0xa58750
~0xa51880
~0xa5ecd0
~0xa31f50
~0xa57db0

只有当drop get被接受时才会在关闭应用程序之前调用析构函数。

顺便说一句。 我在一台本土的Qt 5.6 @ 1fcdb6cafcf上 - 在一台计算机上和5.6.0-19.fc23 Fedora 23预编译在另一台计算机上。 所以我怀疑它只是一个临时的发展状态。

只有在忘记删除mimeData()返回的指针时才会发生内存泄漏。 您必须像使用任何指针一样管理所有权。

例如,如果使用setMimeData()mimeData()返回的指针传递给QDrag对象,则他将获取它的所有权,并将在拖动操作结束时将其删除。 在这种情况下没有内存泄漏。

请参阅: http//doc.qt.io/qt-5/qdrag.html#setMimeData

它应该发生,如果不是,那么这是一个错误 - 除了报告尚未报告之外,你无能为力。

我无法在Qt 5.6的OS X上重现它。 它可能是特定于平台的,也可能是旧Qt版本中已修复的错误。 只要在拖动结束时释放鼠标按钮,mime数据就会被删除。 析构函数执行时的调用堆栈具有通过deleteLater某处调用事件循环的QDrag析构函数。 我已经逐字地使用了你的代码。

补充工具栏:如果你真的希望它尽可能短,它可以做得更小。 这就是我得到的,虽然我同意它主要是分裂头发。 通过提供一个有效的例子,你的问题可以胜过99%的其他问题- 对此有很大的荣誉 我认为简洁的事情是:

  1. 包含整个所需的Qt模块。
  2. 使用qDebug而不是std::cout &al,它保存了一个包含Qt风格。
  3. 如果你仍然使用struct ,那么访问说明符并不重要。
  4. 一般来说,析构函数在公共基类中是虚拟的,或者它们永远不会没有屈服于切片。 所以你不必拼写出来。

当然,我有示例代码,我不遵循这一点。 我喜欢称之为遗留代码:)

#include <QtWidgets>

struct TrackedMimeData : QMimeData {
   TrackedMimeData(const QString & text) {
      qDebug() << this;
      setText(text);
   }
   ~TrackedMimeData() {
      qDebug() << "~" << this;
   }
};

struct MyListWidget : QListWidget {
   MyListWidget() {
      setDragEnabled(true);
      addItem("item1");
      addItem("item2");
   }
   QMimeData * mimeData(const QList<QListWidgetItem *>) const override {
      return new TrackedMimeData("hello");
   }
};

int main(int argsc, char *argsv[]) {
   QApplication application(argsc, argsv);
   MyListWidget gui;
   gui.show();
   return application.exec();
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM