Chapitre 23 - Gestion de la mémoire par l'exécutable▲
Limite virtuelle de la mémoire▲
Une fois compilé (commande Run, Compile ou Make de l'éditeur), un programme gère la mémoire très rigoureusement. Le tableau ci-dessous vous montre que les variables globales, les variables locales des sous-programmes et les pointeurs ne sont pas stockés dans les mêmes parties de la mémoire. En effet, les variables globales ont la part belle, la mémoire allouée aux pointeurs est variable et celle destinée aux variables locales est assez restreinte.
Zone mémoire |
Taille |
Utilisation |
---|---|---|
Pile (Stack) |
16 ko par défaut |
Destiné aux variables locales des sous-programmes (procédures, fonctions) ainsi qu'aux valeurs passées par valeur aux sous-programmes |
Tas (Heap) |
de 0 Ã 640 ko |
Réservé aux pointeurs |
Segment de données |
64 ko |
Destiné aux variables du programme principal |
Explications :
les sous-programmes étant destinés à des calculs intermédiaires, ils n'ont guère besoin d'énormément de ressource mémoire. Quant aux pointeurs que l'on verra dans le chapitre suivant, ils sont destinés à la création de variables (dites dynamiques) au cours de l'exécution du programme.
Mais il est toutefois possible de modifier manuellement une telle organisation de la mémoire afin, par exemple, de privilégier la pile grâce à la directive de compilation suivante :
{$M n1, n2, n3}
Ce type de directive est destiné au compilateur, qui inscrira les informations spécifiées dans le programme compilé. Une directive de compilation se présente entre accolades, comme n'importe quel autre commentaire, mais un signe dollar « $ » signifie qu'il est destiné au compilateur. Quant au « M » il dit au compilateur qu'on souhaite réorganiser la disposition de la mémoire à l'aide des valeurs n1, n2 et n3 qui spécifient respectivement : la taille en kilo octets de la pile (doit être inférieure à 64 ko), la taille minimale et la taille maximale (inférieure à 640 ko) du tas.
Mais pourquoi s'enquiquiner avec ça ? Tout simplement parce qu'il pourra vous arriver d'avoir insuffisamment de mémoire à cause d'un tableau trop long par exemple. Si vous déclarez une telle variable dans une procédure (une variable locale, donc) :
Var
Tableau : Array
[1
..50
, 1
..100
] of
Real
;
vous obtiendrez le message d'erreur n° 22 : Structure too large, qui veut dire que votre variable tient trop de place pour être stockée dans la mémoire allouée. Car, ce tableau occupe : 50 * 100 * 6 octets = 29 ko (1 ko = 2^10 = 1024 octets) 29 ko > 16 ko donc le compilateur renvoie une erreur. Et le seul moyen qui vous reste est de modifier les valeurs correspondantes aux grandeurs allouées à la pile par une directive de compilation ou en allant dans le menu Option/Memory Size. D'où l'intérêt du chapitre 4 (« Différents types de variables »), qui vous indique la taille de chaque type de variable.
Passage de paramètre à un sous-programme▲
Dans le chapitre 7 (« Procédures et sous-programmes »), vous avez appris qu'on pouvait passer un paramètre par valeur ou bien par adresse à une procédure paramétrée. Vous avez également compris l'intérêt de la syntaxe Var dans la déclaration d'une procédure.
Quand un sous-programme est appelé, le programme compilé réalise en mémoire (dans la pile) une copie de chaque argument passé au sous-programme. Ces copies ne sont que temporaires, puisque destinées au fonctionnement de sous-programmes qui n'interviennent que temporairement dans le programme. Ainsi un changement de valeur au sein de la procédure d'un paramètre passé par valeur (sans le var) n'est pas répercuté dans le programme principal. Alors que dans le cas de la présence du mot-clé var, le programme ne duplique pas la valeur ainsi passée à la procédure dans la pile, mais passe l'adresse de la variable utilisée comme paramètre réel, ce qui permet à la procédure/fonction d'accéder à la variable du programme appelant, puisqu'elle connaît son adresse en mémoire. Ainsi, toute variation interne à la procédure est répercutée directement sur l'argument (la variable du programme principal passé en paramètre).