Eviter les fuites de mémoire lors de la manipulation d'objets JSON

Je vous ai déjà parlé de la librairie System.JSON de manipulation de données au format JSON fournie avec Delphi en tant que système simple pour stocker des informations dans un programme (paramètres ou autres) mais aussi pour les risques de violations d'accès en cas de mauvaise utilisation.

A l'occasion de quelques modifications dans mon unité de stockage de configurations en JSON, je me suis dit qu'il ne serait pas idiot de vous alerter sur un truc tout bête qui peut causer des fuites de mémoire si on n'y fait pas gaffe.

Pour modifier les valeurs associées à une propriété d'objet JSON, je commence généralement par chercher si cette clé existe déjà dans l'objet, puis je la supprime et j'ajoute une nouvelle version avec la nouvelle valeur.

  if (jso.Count > 0) and (nil <> jso.getValue(key)) then
    jso.RemovePair(key).Free;
  jso.AddPair(key, value);

Le retrait de la paire depuis l'objet s'effectue avec RemovePair qui nous retourne un pointeur vers cette paire après l'avoir retirée de l'objet. Le hic c'est que si on n'en fait rien, elle reste en mémoire inutilement.Si on retire un élément de l'objet JSON, il faut penser à en supprimer l'instance, d'où le Free ajouté derrière RemovePair dans le code ci-dessus.

Par rapport à cette façon de faire, il y a plusieurs opérations en mémoire : déjà la recherche de la paire à deux reprises, des manipulations sur la liste des propriétés de l'objet (suppression puis ajout d'une paire) et enfin la suppression puis la création d'une paire. Loin d'être certain que ce soit hyper optimisé en terme d'utilisation CPU et de gestion mémoire même si on ne génère pas de fuites en n'oubliant pas de supprimer la paire retirée de l'objet.

Si le CPU nous intéresse, il y a une autre possibilité : chercher si la paire existe déjà et modifier sa valeur directement si tel est le cas.

  pair := jso.Get(key);
  if assigned(pair) then
    pair.JsonValue := tjsonstring.Create(value)
  else
    jso.AddPair(key, value);

Il oblige à avoir une variable temporaire (qu'on peut déclarer localement depuis l'avénement des variables inline) mais il fait moins de manipulations donc devrait être plus léger en terme de CPU, de consommation de batterie si vous êtes sur mobile ou tablette et de mouvements dans la mémoire.

A tester dans vos projets.

Les fuites de mémoire c'est tout bête, nous venons d'en voir un exemplaire facilement évitable. Alors pensez-y quand vous manipulez du JSON ou d'autres types de données qui ne se détruisent que si vous le demandez vous-même.


A lire aussi

Insérer un enregistrement dans un ensemble de données depuis une grille avec LiveBindings (30/05/2020)
Eviter les fuites de mémoire lors de la manipulation d'objets JSON (11/05/2020)
Pourquoi vouloir ajouter ()?: au Pascal alors qu'on a ifthen() ? (11/05/2020)
Plutôt INI ou JSON pour stocker vos paramètres ? (11/05/2020)
Quel composant utiliser pour dialoguer sur le port série de l'ordinateur ? (31/05/2019)
Utilisation de processus sous Delphi : fonctionnement de base. (30/07/2018)
Les threads et le blocage des écrans (30/07/2018)
Evitez les plantages causés par une mauvaise utilisation de la librairie System.JSON (18/04/2018)
Calculer et vérifier un checksum pour dialoguer avec l'extérieur (19/07/2017)
Télécharger simplement un fichier via Internet en tâche de fond (10/07/2017)
Calculer un MD5 sous Delphi (04/07/2017)
Passer un traitement lourd en tâche de fond sans bloquer l'écran (04/06/2017)
Ajouter des chaînes de caractères vides dans un objet JSON (19/05/2017)
Configurer le firewall de McAfee AntiVirus Plus pour utiliser l'App Tethering (28/06/2016)

Membre du programme MVP.
Membre du programme MVP