Introduction
Le modèle d'exécution d'un programme sur un processeur correspond à
celui de la programmation impérative. Plus précisément, un
programme est une série d'instructions dont l'exécution modifie
l'état mémoire de la machine. Cette mémoire est
constituée principalement des valeurs créées ou manipulées par le
programme. Or, comme toute ressource informatique, la mémoire
disponible pour une application est une denrée finie ; un programme
tentant d'utiliser plus de ressources que le système ne lui en
attribue se retrouvera dans un état incohérent. Pour cette raison, il
est nécessaire d'optimiser l'utilisation de la mémoire en
réutilisant la place occupée par des valeurs qui à un instant
donné ne sont plus nécessaires à la suite de
l'exécution. Cette gestion mémoire a une influence importante sur
l'exécution du programmme et sur son efficacité.
Le fait de réserver une zone de la mémoire pour en faire un
certain usage s'appelle l'allocation de mémoire. On distingue
l'allocation statique qui est effectuée au chargement du
programme c'est-à-dire avant son exécution proprement dite, et
l'allocation dynamique qui intervient au cours même de
l'exécution. Alors que la mémoire allouée statiquement le reste
jusqu'à la fin du programme, les zones allouées dynamiquement sont
susceptibles d'être libérées, voire d'être réaffectées durant
l'exécution.
La récupération d'une zone mémoire fait courir deux risques :
-
si une zone mémoire est libérée alors qu'elle
contient une valeur encore utilisée, cette valeur risque d'être
corrompue lorsque le programme y accédera, on parle alors de
pointeurs fantômes ;
- si la localisation (l'adresse) d'une zone
mémoire n'est plus connue alors celle-ci ne pourra plus être
libérée avant la fin du programme. On parle alors de fuite de
mémoire.
Lorsque la gestion de la mémoire est effectuée par le programmeur,
elle demande beaucoup de soins à ce dernier pour éviter ces deux
écueils. Et cela peut s'avérer assez ardu quand les structures de
données manipulées par le programme sont complexes et en
particulier quand elles partagent une même zone mémoire.
Pour décharger le programmeur de cet exercice difficile, des
mécanismes de récupération automatique de la mémoire ont
été introduits dans de nombreux langages. L'idée maîtresse est
qu'à un moment quelconque de l'exécution, les seules valeurs
allouées dynamiquement susceptibles d'être utiles sont
celles dont le programme connaît directement ou indirectement
l'adresse. Toutes les valeurs qui ne peuvent plus être atteintes ne
le pourront pas plus dans le futur donc leur zone mémoire
peut être récupérée. Cette récupération peut se faire
immédiatement après qu'une valeur est devenue inutilisable, ou de
manière retardée quand le programme a besoin de plus de place
qu'il n'en dispose.
Objective CAML dispose d'un tel mécanisme, appelé GC (Garbage
Collector en anglais et Glaneur de Cellules en français). La mémoire
est allouée à la construction d'une valeur (i.e. à l'application d'un
constructeur) et est libérée implicitement. Dans la plupart des
programmes, il n'est besoin de connaître du GC que son existence
car il joue son rôle de façon transparente. Par contre, ce mécanisme
de gestion de mémoire peut avoir des conséquences sur l'efficacité
du programme pour des applications créant très souvent de
nouvelles valeurs. Dans de tels cas, il est utile d'avoir accès aux
paramètres du GC, voire de pouvoir explicitement l'invoquer.
De plus, il est nécessaire de comprendre ce qu'impose le GC à la
représentation des données pour interfacer Objective CAML avec un autre
langage de programmation tel que cela est décrit dans le chapitre
12.