我刚刚提供了this问题的答案,并希望提供一个工作示例,当我发现QMimeData
返回的新创建的QListModel::mimeData()
实例在应用程序获取之前不会被删除终止。
因此,这不是真正的内存泄漏,因为Qt会在关机时处理所有QMimeData
实例,但您只需拖放足够长的时间并将正确的内容放入您的mime数据中让记忆力充足。
我错过了什么吗?有没有办法告诉Qt一旦不再需要它们就删除QMimeData
个实例?
请注意:
我知道Qt会在程序终止时自动删除QMimeData
的每个实例。
我的问题不是由valgrind
或cppcheck
报告的真正的内存泄漏,但看起来多个且可能非常大的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预编译在另一台计算机上。所以我怀疑它只是一个临时的发展状态。
答案 0 :(得分:2)
只有在忘记删除mimeData()
返回的指针时才会发生内存泄漏。您必须像使用任何指针一样管理所有权。
例如,如果您使用mimeData()
将QDrag
返回的指针传递给setMimeData()
对象,他将取得它的所有权,并将在最后删除它拖动操作。在这种情况下没有内存泄漏。
答案 1 :(得分:1)
它应该发生,如果不是,那么这是一个错误 - 除了报告尚未报告之外,你无能为力。
我无法在Qt 5.6的OS X上重现它。它可能是特定于平台的,也可能是旧Qt版本中已修复的错误。只要在拖动结束时释放鼠标按钮,mime数据就会被删除。析构函数执行时的调用堆栈具有通过QDrag
某处的事件循环调用的deleteLater
析构函数。我已经逐字地使用了你的代码。
补充工具栏:如果你真的希望它尽可能短,那么它可以做得更小一些。这就是我得到的,虽然我同意它主要是分裂头发。你的问题通过提供一个有效的例子来胜过99%的其他问题 - 对此有很大的荣誉!我认为简洁的事情是:
qDebug
代替std::cout
&amp; al,它保存了一个包含更多的Qt风格。struct
,访问说明符无关紧要。我有示例代码,当然我不遵循这个。我喜欢称之为遗留代码:)
#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();
}