Avec des langages comme le C++, le développeur doit gérer le cycle de vie des objets dans son code. C’est à lui de les détruire et libérer la mémoire s’il veut éviter les fuites. En C#, c’est différent. Le Garbage collector (GC) se charge de libérer de la mémoire si nécessaire et le développeur n’a en général pas à s’en soucier tant qu’il utilise du code managé. Lorsqu’il utilise du code non managé, lors de l’accès à un fichier ou à une base de données par exemple, la destruction des objets sera manuelle. Cet article nous donnera un aperçu du fonctionnement du Garbage collector et nous indiquera comment gérer la destruction des objets avec du code non managé.
Le Garbage collector
Le Garbage collector (GC) est chargé de gérer la mémoire de notre application. Son exécution permet de la libérer. Pour ce faire, il recherche les objets qui ne sont plus utilisés par l’application et les détruit. Il évite ainsi les fuites de mémoire.
Le Common Language Runtime (CLR) .NET réserve une certaine quantité de mémoire qui sera utilisée par les objets de notre application. Si notre appli a besoin de plus de mémoire, le CLR préfère libérer de la mémoire qu’augmenter la quantité de mémoire nécessaire. C’est là qu’intervient le GC.
Le GC utilise 3 segments de mémoire appelés génération:
- Génération 0: objets à courte durée de vie. Le GC s’exécute souvent pour ces objets.
- Génération 1: segment intermédiaire entre les génération 0 et 2
- Génération 2: les objets de grande tailles et à longue durée de vie
Les nouveaux et petits objets sont alloués à la génération 0. Lorsque le GC s’exécute, il détruit les objets qui ne sont plus utilisés. Ceux qui survivent vont à la génération 1. Si malgré le traitement de la génération 0, il y a toujours un manque de mémoire, le GC traite la gen 1 puis la gen 2 si nécessaire. Le GC récupère l’espace des objets détruits.
Le GC a des points faibles:
- il met en pause l’exécution de tous les threads pour s’exécuter
- un seul thread fait tout le travail
- la récupération de la mémoire de la génération 2 est long
GC.Collect() permet de forcer l’exécution du GC. Cependant, l’appel à la méthode ne garantit pas l’exécution immédiate. Il programme l’exécution du GC mais on ne peut prévoir à quel moment elle se fera.
Utilisation de code non managé
Le Garbage collector se charge de la mémoire dans la plupart des cas. Lorsque notre code contient des objets utilisant des ressources non managées, la gestion de la mémoire est manuelle. Les ressources non managées sont par exemple des ressources systèmes, l’accès à des fichiers ou des connexions aux bases de données.
L’un des moyens pour y parvenir est d’implémenter la méthode Dispose de l’interface IDisposable. Cette méthode devra contenir le code chargé de libérer explicitement la mémoire des ressources non managées.
Un autre moyen est de créer un destructeur. Il sera appelé automatiquement lors de l’exécution du Garbage collector. En c#, le destructeur porte le nom de la classe précédé du signe ~
La différence entre les deux moyens est qu’avec la méthode Dispose, on sait quand la mémoire sera libérée, vu que c’est nous qui l’appelons. Or avec le destructeur, la libération de la mémoire se fera lors de l’exécution du Garbage collector qui n’est pas déterministe.
Rien n’empêche de créer un destructeur et d’implémenter la méthode Dispose. Ainsi, on est sur que le destructeur s’exécutera au cas où le développeur oublie d’appeler Dispose. Un moyen plus efficace est d’utiliser le mot-clé using. Avec using, on est sur que l’objet sera détruit. La méthode Dispose est automatiquement appelé à la sortie de la section.
using (StreamReader s = new StreamReader("File1.txt")) // using ne fonctionne qu'avec les objets implémentant IDisposable { // je traite mon fichier } // à la sortie Dispose() est appelé automatiquement
Conclusion
Le Garbage collector nous facilite la vie en détruisant pour nous les objets qui ne sont plus utilisés par notre code. Le développeur n’a plus qu’à gérer la libération de la mémoire utilisée par les ressources non managées. Cette gestion n’a rien de compliquée comme on vient de le voir. On est bien loin des malloc du langage C.
Laisser un commentaire