Memory leak in Qt5? How to remove QMimeData?

I just answered this question and wanted to provide a working example when I noticed that the newly created QMimeData instance returned by QListModel::mimeData() will not be deleted until the application is completed.

Thus, this is not a real memory leak, since Qt processes all instances of QMimeData at shutdown, but you only need to drag and drop and just drag and drop the desired content into your mime data to make the memory fully work.

Did I miss something? Is there any way to tell Qt to remove instances of QMimeData as soon as they are no longer needed?

Note:

I know that every instance of QMimeData automatically deleted by Qt when the program terminates. My problem here is not the actual memory leak reported by valgrind or cppcheck , but it seems that multiple instances and potentially very large instances of QMimeData not cleared at runtime, which also increases memory consumption.

Code example:

 #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(); } 

An example output is as follows:

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

Destructors are called before closing the application only when drop is accepted.

Btw. I am on home Qt 5.6 @ 1fcdb6cafcf - on one computer and on 5.6.0-19.fc23 Fedora 23 is precompiled on another. Therefore, I doubt that this is only a temporary state of development.

+5
source share
2 answers

There is a memory leak only if you forgot to delete the pointer returned by mimeData() . You must manage the property, as with any pointer.

For example, if you pass the returned mimeData() pointer to a QDrag object using setMimeData() , it will take control of it and take care of deleting it at the end of the drag operation. In this case, there is no memory leak.

See: http://doc.qt.io/qt-5/qdrag.html#setMimeData

+2
source

This should happen, if it’s not, then it’s a mistake - you can’t do anything about it except to report it if it has not been sent yet.

I cannot play it on OS X with Qt 5.6. This may be platform specific or an already fixed bug in the old version of Qt. As soon as I release the mouse button at the end of the drag, the mime data is deleted. In the call stack, when the destructor is executed, there is a QDrag destructor called from the event loop through deleteLater somewhere. I used your code verbatim.

Sidebar: it can be made a little more minimal if you really wanted it as short as possible. Here is what I got, although I agree that it is basically hair splitting. Your question beats 99% of other questions , providing a working example - a great advantage for this ! What, in my opinion, matters for brevity:

  • Inclusion of all necessary Qt module (s).
  • Using qDebug instead of std::cout and al, it preserves inclusion and more Qt style.
  • Access specifiers don't matter if you use struct anyway.
  • Generally speaking, destructors are either virtual in a publicly accessible base class, or they can never be without cuttable ones. So you do not need to do this.

I have an example code where I do not follow this, of course. I like to call it obsolete code :)

 #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(); } 
+1
source

All Articles