Présentation de la mémoire des programmes C
Une représentation typique du programme C en mémoire comprend les sections suivantes.
- Segment de texte
- Segment de données initialisées
- Segment de données non initialisées
- pile
- tas
Segment de texte
Un segment de texte, également appelé segment de code ou simplement texte, est l'une des sections d'un programme dans un fichier objet ou en mémoire, qui contient des instructions exécutables.
En tant que région de mémoire, un segment de texte peut être placé sous le tas ou la pile afin d'empêcher les tas et les débordements de pile de l'écraser.
En général, le segment de texte est partageable, de sorte qu'une seule copie doit être en mémoire pour les programmes fréquemment exécutés, tels que les éditeurs de texte, le compilateur C, les shells, etc. De plus, le segment de texte est souvent en lecture seule afin d'empêcher un programme de modifier accidentellement ses instructions.
Segment de données initialisées
Segment de données initialisé, généralement appelé simplement le segment de données. Un segment de données est une partie de l'espace d'adressage virtuel d'un programme, qui contient les variables globales et les variables statiques initialisées par le programmeur.
Notez que le segment de données n'est pas en lecture seule, car les valeurs des variables peuvent être modifiées au moment de l'exécution.
Ce segment peut en outre être classé en zone de lecture seule initialisée et en zone de lecture/écriture initialisée.
Par exemple, la chaîne globale définie par char s[] = "hello world" en C et une instruction C telle que int debug = 1 en dehors de la zone principale (main) sont stockées dans une zone de lecture-écriture initialisée. Et une instruction C globale telle que const char * string = “hello world” fait que le littéral de chaîne “hello world” soit stocké dans la zone de lecture seule initialisée et que le pointeur de caractère se trouve dans la zone de lecture-écriture initialisée.
Segment de données non initialisées
Segment de données non initialisé, souvent appelé le segment "bss". Les données de ce segment sont initialisées par le noyau sur une valeur arithmétique égale à 0 avant que le programme ne commence à s'exécuter.
Les données non initialisées commencent à la fin du segment de données et contiennent toutes les variables globales et les variables statiques initialisées à zéro ou n'ayant pas d'initialisation explicite dans le code source.
Pile
La zone de la pile était traditionnellement contiguë à la zone du tas et se développait dans la direction opposée; lorsque le pointeur de pile rencontre le pointeur de tas, la mémoire disponible est épuisée. (Avec les grands espaces d'adresses modernes et les techniques de mémoire virtuelle, ils peuvent être placés presque n'importe où, mais ils poussent toujours dans des directions opposées.)
La zone de la pile contient la pile du programme, une structure LIFO, typiquement située dans les parties supérieures de la mémoire. Sur L'architecture standard PC x86, il croît vers l'adresse zéro; sur d'autres architectures, il croît dans la direction opposée. Un registre "pointeur de pile“ suit le haut de la pile; il est ajusté chaque fois qu'une valeur est "poussée" sur la pile. L'ensemble des valeurs poussé pour un appel de fonction est appelé un “cadre de pile”; Un cadre de pile se compose au minimum d'une adresse de retour.
Pile, où les variables automatiques sont stockées, ainsi que l'information qui est enregistrée chaque fois qu'une fonction est appelée. Chaque fois qu'une fonction est appelée, l'adresse où retourner et certains renseignements sur l'environnement de l'appelant, comme certains registres de la machine, sont sauvegardés sur la pile. La fonction nouvellement appelée alloue alors de la place sur la pile pour ses variables automatiques et temporaires. C'est ainsi que les fonctions récursives en C peuvent fonctionner. Chaque fois qu'une fonction récursive s'appelle elle-même, un nouveau cadre de pile est utilisé, de sorte qu'un ensemble de variables n'interfère pas avec les variables d'une autre instance de la fonction.
Tas
Tas est le segment où l'allocation dynamique de la mémoire a généralement lieu.
La zone de tas commence à la fin du segment BSS et se développe à partir de là. Elle est gérée par malloc, realloc et free, qui peut utiliser les appels système brk et sbrk pour en ajuster la taille (notez que l'utilisation de brk / sbrk et une seule "zone de tas" n'est pas nécessaire pour satisfaire malloc/realloc/free; ils peuvent également être implémentés en utilisant mmap pour réserver des régions de mémoire virtuelle potentiellement non contiguës dans l'espace d'adressage virtuel du processus.
La zone de Tas est partagée par toutes les bibliothèques partagées et les modules chargés dynamiquement dans un processus.