Je viens de fournir une réponse à cette question et souhaitais fournir un exemple de travail lorsque j’ai remarqué que l’instance QMimeData
nouvellement créée, renvoyée par QListModel::mimeData()
, ne sera supprimée que lorsque l’application sera terminée.
Il ne s’agit donc pas d’une véritable fuite de mémoire puisque Qt gère toutes les instances de QMimeData
à l’arrêt, mais il vous suffit de faire glisser et de déposer suffisamment de temps et de placer le bon contenu dans vos données mime pour que la mémoire soit saturée.
Ai-je manqué quelque chose? Existe-t-il un moyen d’indiquer à Qt de supprimer les instances de QMimeData
dès qu’elles ne sont plus nécessaires?
Notez s’il vous plaît:
Je sais que chaque instance de QMimeData
est automatiquement supprimée par Qt à la fin du programme. Mon problème ici n’est pas une fuite de mémoire réelle telle que rapscope par valgrind
ou cppcheck
mais il semble que les instances multiples et potentiellement très volumineuses de QMimeData
ne soient pas nettoyées au moment de l’exécution, ce qui augmente également la consommation de mémoire.
Exemple de code:
#include #include struct TrackedMimeData : public QMimeData { TrackedMimeData(const QSsortingng & 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) const override { return new TrackedMimeData("hello"); } }; int main(int argsc, char *argsv[]) { QApplication application(argsc, argsv); MyListWidget gui; gui.show(); return application.exec(); }
Exemple de sortie ressemble à ceci:
0xa58750 0xa4e0f0 ~0xa4e0f0 0xa3c6c0 ~0xa3c6c0 0xa51880 0xa5ecd0 0xa31f50 0xa57db0 0xa5afc0 ~0xa5afc0 0xa5aa70 ~0xa5aa70 ------ CLOSE WINDOW ~0xa58750 ~0xa51880 ~0xa5ecd0 ~0xa31f50 ~0xa57db0
Les destructeurs sont appelés avant la fermeture de l’application uniquement lorsque la suppression est acceptée.
Btw. Je suis sur un Qt 5.6 @ 1fcdb6cafcf maison – sur un ordinateur et sur 5.6.0-19.fc23 Fedora 23 précompilé sur un autre. Donc, je doute que ce soit juste un état de développement temporaire.
Il y a une fuite de mémoire uniquement si vous oubliez de supprimer le pointeur renvoyé par mimeData()
. Vous devez gérer la propriété comme avec n’importe quel pointeur.
Par exemple, si vous transmettez le pointeur renvoyé par mimeData()
à un object QDrag
aide de setMimeData()
, il en prendra possession et se chargera de le supprimer à la fin de l’opération de glissement. Il n’y a pas de fuite de mémoire dans ce cas.
Cela devrait arriver, si ce n’est pas le cas, alors c’est un bogue – vous ne pouvez rien y faire, à part le signaler s’il n’a pas encore été signalé.
Je ne peux pas le reproduire sur OS X avec Qt 5.6. Il peut s’agir d’une plate-forme spécifique ou d’un bogue déjà corrigé dans une ancienne version de Qt. Dès que je relâche le bouton de la souris à la fin du glissement, les données mime sont supprimées. Lorsque le destructeur s’exécute, la stack d’appels appelle le destructeur QDrag
partir de la boucle d’événements via deleteLater
quelque part. J’ai utilisé votre code mot à mot.
Encadré: Cela pourrait être légèrement plus minimal si vous le vouliez aussi court que possible. Voici ce que j’ai, bien que je convienne que c’est principalement couper les cheveux en deux. Votre question bat 99% des autres questions en fournissant un exemple concret – un grand bravo pour cela ! Les choses qui, à mon avis, importent pour la brièveté sont:
qDebug
au lieu de std::cout
& al, cela enregistre un include et est plus du style Qt. struct
. J’ai un exemple de code où je ne suis pas cela, bien sûr. J’aime l’appeler le code hérité 🙂
#include struct TrackedMimeData : QMimeData { TrackedMimeData(const QSsortingng & text) { qDebug() << this; setText(text); } ~TrackedMimeData() { qDebug() << "~" << this; } }; struct MyListWidget : QListWidget { MyListWidget() { setDragEnabled(true); addItem("item1"); addItem("item2"); } QMimeData * mimeData(const QList) const override { return new TrackedMimeData("hello"); } }; int main(int argsc, char *argsv[]) { QApplication application(argsc, argsv); MyListWidget gui; gui.show(); return application.exec(); }