Je viens d'installer Delphi 10.2 Release 1. Lorsque je recompile mes applications et que je les lance, je reçois beaucoup de fuites de mémoire. Je n'ai eu aucune fuite de mémoire avec 10.2 (sans la mise à jour). Je n'ai apporté aucune modification au code non plus.
Pour vérifier, j'ai créé une simple application vierge et mis quelques composants sur le formulaire. Pas de code. A exécuté l'application et a obtenu des fuites de mémoire.
Je voulais souligner ceci (ne serait-ce que comme avertissement avant de procéder à la mise à niveau).
Mes questions:
Remarque: J'ai enregistré un problème sur le portail de qualité, juste au cas où il s'agirait d'un problème réel: https://quality.embarcadero.com/browse/RSP-18774 . Dans ce billet, j'ai également joint l'exemple d'application.
Après quelques recherches, j'ai découvert que les rappels transmis à TThread.CurrentThread.ForceQueue
dans TStyledControl.KillResourceLink
ne sont jamais exécutés, car avant qu'un thread puisse les gérer, l'application se termine et le destructeur de classe TThread
détruit la liste contenant des rappels non gérés.
J'ai résolu ce problème en ajoutant un appel à CheckSynchronize
à la fin de FMX.Forms.DoneApplication
, ce qui force l'exécution des rappels, ce qui a résolu l'énorme fuite de mémoire.
Je ne sais pas s'il s'agit du correctif correct du problème, mais cela a résolu le problème des fuites de mémoire signalées.
J'ai le même problème en utilisant C++ Builder 10.2.1 dans les applications FMX et VCL.
Si j'active CodeGuard, des fuites de mémoire se produisent à la fermeture de l'application.
J'ai un gestionnaire TThread
avec OnTerminate
: si je mets un point d'arrêt dans ce gestionnaire, lorsque je ferme le programme, il n'est jamais appelé.
Si je mets CheckSynchronize()
dans le destructeur de mon formulaire de demande principal, le problème persiste.
Ma solution était une boucle "horrible" comme celle-ci dans le destructeur de la forme principale:
__fastcall TForm3::~TForm3(void) {
for(int i = 0; i < 10; i++) {
Sleep(1);
CheckSynchronize();
}
}
Cette solution n'est pas déterministe mais peut être utilisée dans votre application en mode débogage pour éviter les messages d'erreur CodeGuard.
Une autre solution consiste à utiliser la fonction WaitFor()
si MyThread
est un objet TThread
:
MyThread = new MyThreadClass();
et DeleteThisTh()
est une méthode de cette classe, nous pouvons attendre le thread terminé à l'intérieur de DeleteThisTh()
:
void MyThreadClass::DeleteThisTh(void) {
Terminate();
WaitFor();
delete this;
}
Dans l'événement OnTerminate
, je peux nettoyer mes objets. Prendre note:
delete this
est appelé après OnTerminate
;DeleteThisTh()
habite dans le thread principal;