Un système de ramasse miette en C

Je viens d’implémenter dans mon shell un système de ramasse miette. Le choix de faire un tel système est particulièrement adapté pour un shell ou pour tout programme qui est fortement cyclique et avec un cycle assez court où chaque allocation peut être libérée rapidement.

En gros l’astuce consiste à créer des fonctions wrapper pour free(3) et malloc(3). Une fois que tous nos appels d’allocation et de libération de mémoire passent par eux il est facile de créer une structure de type pile qui empile l’adresse de chaque allocation pour ensuite tout libérer d’un coup à la fin du cycle.

Pour cela j’ai utilisé les SLIST de sys/queue.h pour la pile que voilà :

typedef struct stack_s {
void * adr;
SLIST_ENTRY(stack_s) next;
} stack_s;

Ensuite le wrapper pour malloc (notez qu’on déclare la tête de pile comme variable globale (dans le fichier avec les fonctions wrapper) pour pouvoir y accéder facilement.

/* déclaration de la pile mstack (qu'on initialise à NULL) */
static SLIST_HEAD(, stack_s) mstack = SLIST_HEAD_INITIALIZER(&mstack);
/* Le wrapper pour malloc */
void *
xmalloc(size_t size)
{
void *ret;
stack_s *el; /* l'élément a rajouter dans la pile */
ret = malloc(size);
if (!ret)
{
perror("Malloc ");
exit (EXIT_FAILURE);
}
el = malloc(sizeof(*el));
el->adr = ret;
SLIST_INSERT_HEAD(&mstack, el, next);
return ret;
}
/* Cette fonction vide toute la pile et libère la mémoire */
void
stack_delete(void)
{
stack_s *el;
while (!SLIST_EMPTY(&mstack))
{
el = SLIST_FIRST(&mstack);
SLIST_REMOVE_HEAD(&mstack, next);
free(el->adr);
free(el);
}
return;
}

Voilà, maintenant faites tous vos allocations temporaires avec _malloc et videz la pile de temps en temps (ie à la fin du cycle général de votre programme).

Par exemple dans la boucle principale ça donne quelque chose comme ça :

for (;;)
{
machin = xmalloc(sizeof(*machin) * 10);
/*
...
...
*/
stack_delete();
}

J’espère que c’est compréhensible, si vous avez une question n’hésitez surtout pas à me demander plus d’information.