Tout ce que vous devez savoir (ou presque) sur la pile et le tas

capucine lacroix-blum
4 min readDec 29, 2018

--

Il existe deux ressources clés en informatique, vous ne serez pas surpris de savoir qu’il s’agit du temps d’une part, et de l’espace de stockage de l’autre. Ici, c’est de l’espace de stockage dont il est question. On distingue alors trois stratégies d’allocations de la mémoire, dont deux qui vont nous intéresser plus particulièrement :

D’abord l’allocation statique. Elle se fait avant même l’exécution du programme, car elle concerne les variables globales, déclarées en dehors d’une fonction, entièrement connues, fixées et auxquelles on doit pouvoir accéder n’importe où dans le programme. Le compilateur allouera alors la variable en question de manière statique dans un segment (partie de la mémoire elle-même statique).

Vous vous demandez alors où sont la pile et le tas dans cette histoire… Nous y arrivons justement, car les deux autres stratégies ne sont autres que l’allocation dynamique sur la pile (stack) et l’allocation dynamique sur le tas (heap). Toutes deux se font pendant l’exécution d’un programme et il est important de retenir que c’est là leur seul et unique point commun.

La pile

La pile fonctionne comme la structure de données du même nom, c’est-à-dire selon le principe du LIFO (last in, first out) ou dernier arrivé, premier sorti si vous êtes plus un crack de l’informatique que de l’anglais. Mais qu’empile-t-on ? me demanderez-vous. En fait, lors de l’exécution d’un programme, chaque appel de fonction implique la création d’un nouveau bloc au sommet de la pile, correspondant à la fonction en question. L’intérêt du LIFO prend alors tout son sens : cela permet de connaitre l'endroit où chaque fonction active (dont l’exécution n’est pas terminée) doit retourner à la fin de son exécution.

La pile stocke également les données associées à chaque fonction, telles que les variables locales, les paramètres, etc… Lorsqu’une fonction se termine, le bloc de la pile correspondant, nécessairement au sommet de celle-ci, est libéré, donc les variables placées dans la pile par cette fonction sont supprimées. Voyez plutôt le schéma ci-dessous qui représente une pile stockant des données pour deux fonctions très simples elles-mêmes détaillées à gauche :

Considérons une méthode f1. Un bloc de la pile sera alors créé et dédié à cette méthode, il stockera également la variable x. Puis f1 appelle la méthode f2, impliquant la création du bloc f2 au-dessus de celui de f1. Les variables a et b seront également créées dans le bloc f2. Celui-ci sera supprimé lorsque la méthode f2 aura renvoyé f2(3) comme demandé par la méthode f1.

On comprend alors qu’une fonction imbriquée se situera au-dessus de la fonction englobante dans la pile, et aura ainsi inéluctablement accès à ses données. Nous voilà rassurés ! Mais attention, si l’accumulation des blocs consomme tout l’espace alloué à la pile d’exécution, une erreur se produit : c’est le dépassement de pile. Mais la pile présente un avantage considérable : elle est gérée efficacement par le processeur, pour vous. Les allocations et « désallocations » (libération d’un nouvel espace disponible) se font automatiquement à chaque entrée et sortie de routine. Bien que la pile présente de nombreux avantages, il est parfois nécessaire pour le programmeur d’avoir lui-même le contrôle sur la gestion de la mémoire. Intervient alors notre deuxième protagoniste.

Le tas

Vous l’aurez compris, le tas correspond au second segment de mémoire utilisé pour l’allocation dynamique. A la différence de la pile, vous êtes responsable de l’allocation de la mémoire sur le tas, avec l’utilisation de malloc() ou calloc() (fonctions C intégrées). Évidemment, vous devez également gérer l’utilisation de free () pour libérer cette mémoire dès que vous n’en avez plus besoin. Il est très important de le faire afin d’éviter les fuites de mémoire, qui provoquent la saturation de la mémoire machine. Mais comme souvent en informatique, à gros inconvénient correspond gros avantage. En effet, les variables créées sur le tas sont accessibles par n’importe quelle fonction et n’importe où dans le programme, rendant leur portée globale. Il n’en fallait pas plus pour ajouter une contrainte supplémentaire : la gestion de l’accès concurrentiel. De plus, la mémoire sur le tas, plus grande et plus durable que sur la pile, requiert une gestion plus complexe et donc plus lente. En dehors de ça, le tas offre une bien plus grande liberté : au-delà de la portée globale des variables, celles-ci peuvent être redimensionnées à l’aide de la fonction realloc(). De plus, la taille des variables dans le tas n’est pas limitée, du moins seulement par la limite physique de la mémoire.

Pile ou Tas, que choisir ?

· Vous devez allouer un grand bloc de mémoire (grande liste par exemple) et la variable doit pouvoir être modifiable et accessible pendant une longue période : Le tas sera votre meilleur allié !

· Vous utilisez des petites variables dont la portée ne dépasse pas la fonction qui les utilise : utilisez la pile, c’est plus facile et plus rapide.

--

--