Ce n'est pas impossible d'implémenter un ramasse-miettes pour le langage C (et en fait, ils existent, sous la forme d'un simple recherche sur google révèle), il est simplement difficile, parce qu'il peut être difficile de déterminer si une certaine chaîne de bits est un pointeur sur un bloc alloué ou simplement regards comme l'un d'entre eux.
La raison pour laquelle ce problème se pose est que le C (et le C++, d'ailleurs) vous permet de passer d'un type de pointeur à un type intégral, de sorte qu'une variable entière peut contenir une adresse dans un bloc alloué, empêchant le GC de libérer ce bloc, même si cette valeur n'était pas censée être un pointeur.
Par exemple, supposons qu'un bloc de mémoire soit alloué. Supposons que ce bloc de mémoire soit alloué à partir de l'adresse 0x00100000 (1 048 576) et qu'il ait une longueur de 1 Mo, c'est-à-dire qu'il s'étende jusqu'à 0x001FFFFF (2 097 151).
Supposons que je stocke également la taille d'un fichier image dans une variable (appelons-la fileSize). Ce fichier image fait 1,5 Mo (1 572 864 octets).
Ainsi, lorsque le ramasseur d'ordures s'exécutera, il rencontrera mon fileSize
et décide qu'il ne peut pas libérer ce bloc, sous peine d'invalider mon pointeur peut-être. C'est parce que le GC ne sait pas si j'ai fait cela :
int fileSize;
{
char *mem = (char*)malloc(1048576);
fileSize = (int)(mem + 524288);
}
// say GC runs here
ou si je viens de le faire :
int fileSize;
{
char *mem = (char*)malloc(1048576);
fileSize = 1572864;
}
// say GC runs here;
Dans ce dernier cas, il est possible de libérer le bloc à *mem (s'il n'existe pas d'autres références), alors que dans le premier cas, ce n'est pas le cas. Il faut être conservateur et supposer que ce n'est pas le cas, donc la mémoire "fuit" (au moins jusqu'à ce que fileSize sorte du champ d'application ou soit modifié pour une valeur en dehors du bloc alloué).
Mais les collecteurs d'ordures pour le C (et le C++) do existent. La question de savoir s'ils sont utiles ou non est un autre sujet de discussion.