我刚刚回答了这个问题(链接),并且想要提供一个可行的示例,但当我注意到由QListModel::mimeData()
返回的新创建的QMimeData
实例在应用程序终止之前不会被删除时,我决定还是说明一下这个问题。
所以这并不是一个真正的内存泄漏,因为Qt会在关闭时处理所有QMimeData
实例,但您只需要足够长时间地拖放并将正确的内容放入mime数据中,就可以让内存耗尽。
我错过了什么吗?有没有办法告诉Qt在不再需要QMimeData
实例时立即删除它们?
请注意:
我知道每个QMimeData
实例都会在程序终止时由Qt自动删除。我的问题不是像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
只有在确认删除时,析构函数才会在关闭应用程序之前被调用。
顺便提一下,我使用的是自制的Qt 5.6 @1fcdb6cafcf - 在一台计算机上,另一台计算机上预编译了5.6.0-19.fc23 Fedora 23。因此,我怀疑这不仅仅是一个临时的开发状态。
QMimeData
继承自QObject
,并将其数据内部存储为字符串和QVariant
对的QVector
。它具有任何其他QObject
派生类所经历的相同内存管理限制。 - jonspaceharpercppcheck
在这个例子中找不到任何问题,因为QMimeData
实例在结束时被删除了。但在那之前,我可能已经存储了大量数据在成千上万个新的QMimeData
实例中 - 这也就是我承认的 - 不是一个经典的内存泄漏问题。 - fransQMimeData
或QDrag
实例的生命周期,以了解何时会中止拖放操作。目前我无法知道何时隐藏某些“按需放置小部件”,这是令人困扰的。 - frans