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.