【发布时间】:2016-10-17 05:48:27
【问题描述】:
我刚刚为this 问题提供了一个答案,并想提供一个工作示例,因为我注意到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
析构函数被调用之前仅当drop get被接受时关闭应用程序。
顺便说一句。我使用的是国产 Qt 5.6 @1fcdb6cafcf - 在一台计算机上和在另一台计算机上预编译的 5.6.0-19.fc23 Fedora 23 上。所以我怀疑这只是一个暂时的发展状态。
【问题讨论】:
-
QMimeData继承QObject并在内部将其数据存储为QVector字符串和QVariant对。它具有与任何其他QObject派生类体验相同的内存管理限制。 -
cppcheck在此示例中找不到任何内容,因为QMimeData实例在最后被删除。但在那之前,我可能已经在数千个新的QMimeData实例中存储了千兆字节的数据——我承认——这不是典型的内存泄漏。 -
您是否真的看到过多的内存消耗,或者只是担心它可能会发生?
-
这就是,女士们,先生们,您如何通过一个独立的测试用例获得一个当之无愧的甜蜜、甜蜜的业力。应该是每个问题被否决和/或关闭的人的案例研究。我认为如果值得评论缺点,也值得评论优点,以加强良好的行为。干得好。
-
@Jon:我很确定有内存丢失,但首先我想跟踪
QMimeData或QDrag实例的生命周期,以了解拖放操作何时中止。目前我无法知道例如何时隐藏一些“按需放置小部件”。
标签: c++ qt memory-leaks ownership