next up previous contents index
Next: Structures de données génériques Up: No Title Previous: Clonage d'objets

Libération et glanage d'objets

  

Rappelons qu'il y a trois modes d'allocation d'un objet : statique, automatique, et dynamique. L'allocation automatique concerne les objets locaux, qui ne sont pas déclarés static ; ils sont alors automatiquement dés-alloués, c'est-à-dire détruits, en même temps que le bloc d'activation de la fonction qui les a alloués. Les deux autres modes d'allocation n'impliquent pas de dés-allocation avant la fin de l'exécution du programme. Ceci n'est pas un problème pour les objets statiques, qui sont complètement connus avant l'exécution de la fonction main du programme. Par contre, comme les objets dynamiques sont créés en cours d'exécution, il est facile, d'une part, d'excéder les ressources en mémoire du processus, et d'autre part, de conserver des objets dynamiques qui ne sont plus utiles.

Certains langages (Lisp, CAML, Java) sont capables de détecter les objets dynamiques inutiles (plus exactement, inaccessibles) et de les dés-allouer afin de remettre la mémoire qu'ils occupent à la disposition de la procédure d'allocation : ces langages disposent d'un glaneur de cellules [*]. D'autres (Pascal, C, C++), qui n'en disposent pas, font porter la responsabilité de cette dés-allocation sur le programmeur.

     

Quand un objet alloué dynamiquement n'est plus utile, le programme doit comporter une dés-allocation explicite, au moyen d'une fonction de libération . La bibliothèque standard offre ainsi la fonction free, déclarée dans stdlib.h, à laquelle doit être passée l'adresse du bloc dynamique à dés-allouer ; cette fonction est capable de déterminer la taille de ce bloc, qui avait été spécifiée dans l'appel à malloc qui l'avait alloué.

Dans le cas d'un objet alloué dynamiquement par morceaux (et non en un seul bloc), ce qui est le cas des structures chaînées, il faut programmer une fonction de libération spécialisée.

Prenons l'exemple des arbres. La représentation en mémoire d'un arbre étant formée de plusieurs cellules non contigües en mémoire, il faut programmer une fonction de libération spécialisée. La fonction suivante recourt à un parcours en profondeur, avec l'ordre suffixe ; la racine est libérée par free seulement quand les deux sous-arbres ont été libérés (les ordres infixe et préfixe conduiraient à couper prématurément une ou deux branches non encore traitées) :

void tree_free(tree_cell *p) {
  if (!is_empty_cell(p)) {
      tree_free(p->left);
      tree_free(p->right);
      free(p);
    } 
}

  Le glanage proprement dit consiste à insérer dans les différentes fonctions du programme des appels aux fonctions de libération (free ou des fonctions spécialisées) afin de libérer les objets devenus inutiles. Cette tâche, toujours délicate, peut conduire à des erreurs quand le glanage est excessif, par exemple dans le cas de partage de sous-objets (voir figure 27, page [*]). Il y a cependant des cas où elle peut être réalisée de façon systématique par le programmeur. Ainsi, quand l'allocation dynamique est utilisée pour simuler des tableaux dynamiques locaux, c'est à la fonction qui les crée de libérer ces blocs avant de retourner :

int f(int m) {
  double *t = malloc(m*sizeof(double));  /* simule : double t[m]; */
  
  ...
  free(t);
  return ...;
}

next up previous contents index
Next: Structures de données génériques Up: No Title Previous: Clonage d'objets
Jean-Philippe Chancelier
9/29/1998