Lors de l’exécution d’un programme, les données doivent être stockées en mémoire. L’espace occupé et l’emplacement de stockage des données sont déterminés par leur type. Deux zones de mémoire sont utilisées pour conserver les données pendant l’exécution : la Pile (Stack) et le Tas (Heap).
La Pile (Stack)
La pile est un tableau de mémoire contigu qui suit la structure de données Dernier entré, premier sorti (LIFO). Elle stocke trois catégories de données :
- Les valeurs de certains types de variables
- Le contexte d’exécution actuel du programme
- Les paramètres transmis aux méthodes

Les opérations de mémoire sur la pile sont gérées automatiquement par le système, le développeur n’a pas besoin de les manipuler manuellement. Comprendre le fonctionnement interne de la pile facilite grandement l’analyse du flux d’exécution du programme et la lecture de la documentation officielle C#.
Caractéristiques fondamentales de la pile
- On ne peut ajouter ni supprimer des données qu’au sommet de la pile
- Ajout de données au sommet : Push (empiler)
- Récupération de données depuis le sommet : Pop (dépiler)
Spécificités de la mémoire de pile
- Allocation et libération de mémoire extrêmement rapides, espace mémoire contigu
- Cycle de vie lié à l’appel de méthode : la trame de pile est détruite automatiquement une fois la méthode terminée
- Contenu stocké : variables de type valeur, paramètres de méthode, variables locales, contexte d’exécution

Pour mieux comprendre le fonctionnement du tas, observons un exemple de code simple
class Program
{
static void Main(string[] args)
{
int a = 10;
int b = 20;
int sum = Add(a, b);
}
static int Add(int x, int y)
{
return x + y;
}
}
Langage du code : JavaScript (javascript)
Cet exemple a une logique très simple. Dès la première ligne de la fonction Main, point d’entrée du programme, on crée une variable de type entier a, puis la variable b sur la seconde ligne. La troisième ligne appelle la fonction Add en transmettant les valeurs de a et b à l’intérieur de la fonction. x reçoit la valeur de a, y reçoit la valeur de b, la fonction renvoie le résultat de x + y égal à 30 vers l’appelant pour l’affecter à sum. Lorsque la fonction Add finit de s’exécuter, x et y sont dépilés, la valeur de sum devient 30, puis le programme se termine à la fin de Main. Nous détaillons ci-dessous chaque étape du processus d’empilage et de dépilage dans la pile.
Flux d’exécution du programme et processus Push/Pop de la pile





À la fin d’Add, x et y sont des paramètres locaux de cette fonction, ils sont dépilés l’un après l’autre pour libérer de l’espace et assurer le bon fonctionnement du système.
Une fois dépilés, x et y disparaissent ; la valeur 30 renvoyée par Add est transmise à l’appelant pour être stockée dans sum.




Retenez un point essentiel : lors de l’exécution d’une fonction, les variables sont créées de haut en bas et empilées dans l’ordre a → b → entrée dans Add → x → y. À la fin d’Add, x et y sont dépilés, puis sum est empilé ; quand Main se termine, les variables sont détruites dans l’ordre inverse de leur création : sum, b, a.
Le Tas (Heap)
Le tas est une vaste zone de mémoire dédiée à l’allocation dynamique de blocs pour stocker des objets de données. Contrairement à la pile, les données du tas peuvent être ajoutées et supprimées dans n’importe quel ordre.
Le programme ne peut pas supprimer manuellement les objets du tas ; le Ramasse-miettes GC du CLR (Common Language Runtime) nettoie automatiquement les objets orphelins sans référence inaccessible. Cela évite les erreurs liées à la libération manuelle de mémoire indispensable dans d’autres langages.
Le tas peut être comparé à un grand bureau sur lequel on peut poser des objets librement. La pile, quant à elle, ressemble au tube à pièces vu précédemment, avec une seule extrémité pour les entrées et sorties.

Cycle de collecte du GC
- Le programme crée trois objets dans le tas et conserve des références vers eux
- Le programme cesse d’utiliser l’un des objets, toutes ses références disparaissent
- Le GC détecte l’objet orphelin sans référence et libère la mémoire qu’il occupe
- Collecte terminée, la mémoire libérée peut être allouée à de nouveaux objets
Caractéristiques de la mémoire de tas
- Mémoire non contiguë, vitesse d’allocation inférieure à celle de la pile
- Cycle de vie indépendant des limites de méthode, géré de manière centralisée par le GC
- Contenu stocké : instances de types référence (classes, tableaux, délégués…), la pile ne conserve que les adresses mémoire des objets du tas
Voici un exemple concret pour illustrer le fonctionnement. Comme vu précédemment, les variables locales de type primitif sont stockées sur la pile, tandis que les types définis par l’utilisateur résident généralement dans le tas. Voici le code correspondant :
class Program
{
static void Main(string[] args)
{
int a = 10;
int b = 20;
Student tom = new Student("Tom", 12);
Student lucy = new Student("Lucy", 12);
}
}
class Student
{
// Variables membres
private string name;
private int age;
// Constructeur, détaillé plus tard
public Student(string name, int age)
{
this.name = name;
this.age = age;
}
// Méthode membre
public void DisplayInfo()
{
Console.WriteLine($"Name: {name}, Age: {age}");
}
}
Langage du code : JavaScript (javascript)
L’illustration ci-dessous montre le stockage en mémoire des quatre variables a, b, tom et lucy au sein de Main. Comme pour l’explication de la pile, le code s’exécute de haut en bas : a est empilé en premier, puis b. Les valeurs de a et b sont stockées directement sur la pile.


Par exemple, les données de tom se trouvent dans le bloc 00001 du tas, la pile stocke l’adresse 00001 pour retrouver les données par la suite.
Lorsque la fonction Main termine son exécution, la référence d’adresse lucy: 01010 sur la pile est dépilée et détruite. Seule l’adresse disparaît, les données de l’objet dans le tas subsistent. À ce moment-là, l’objet du tas perd toutes les références enregistrées par les variables de la pile.


Zones de mémoire
La pile et le tas sont des divisions logiques de mémoire au niveau logiciel, pas des partitions matérielles physiques.
Pile et tas ne sont que des séparations logiques définies par le logiciel ; la mémoire RAM physique ne possède pas de modules matériels dédiés marqués « zone pile » ou « zone tas ».
La mémoire RAM physique n’est composée que de puces mémoire uniformes avec des adresses physiques continues, aucun marqueur ne distingue la pile du tas au niveau matériel
Le système d’exploitation attribue un espace de mémoire virtuelle indépendant à chaque programme en cours d’exécution, puis divise cette mémoire virtuelle en quatre segments logiques principaux :
Segment de code : Stocke les instructions compilées du programme
Segment statique global : Variables statiques, constantes
Segment de pile (Stack) : Le fil principal et les fils secondaires du programme disposent chacun d’un bloc de pile indépendant
Segment de tas (Heap) : Grand pool de mémoire partagé pour l’allocation dynamique
La pile et le tas évoqués ici ne sont que des zones logiques attribuées par l’OS à chaque processus, sans isolation matérielle entre elles.
Pile contre Tas