Allocation dynamique
Pascal permet l'allocation de mémoire pour une variable soit au moment de la compilation d'un programme, soit de manière dynamique pendant l'exécution du programme.
Les variables déclarées dans une instruction VAR se voient allouer de la mémoire lors de la compilation du programme. Cependant, les variables allouées de manière dynamique ne se voient pas allouer de mémoire tant que le programme en cours d'exécution ne les demande pas via la procédure prédéfinie NEW. Les variables deviennent actives après l'exécution de la procédure NEW et elles restent actives jusqu'à ce que le programme en cours d'exécution localise leur espace en appelant la procédure prédéfinie DISPOSE. L'espace libéré est alors disponible pour être réutilisé par les variables allouées ultérieurement.
Vous ne fournissez pas de nom par lequel référencer une variable allouée de manière dynamique. La variable est référencée indirectement via un pointeur, auquel est attribuée l'adresse mémoire d'une variable allouée de manière dynamique lorsque cette variable est allouée. Avant qu'une variable allouée de manière dynamique ne soit définie ou après qu'elle soit libérée, le pointeur la référençant a une valeur indéfinie. La valeur spéciale NIL, correspondant à l'absence d'adresse mémoire, peut également être attribuée à un pointeur.
Les procédures NEW et DISPOSE allouent et désallouent des variables. (p représente une variable pointeur.) La fonction SIZEOF donne la taille d'une variable dynamique. Une description suit :
Fonction ou procédure | Description |
---|---|
NEW(p) (procédure) |
Définit une variable allouée dynamiquement pointée par p. La variable allouée dynamiquement est du type auquel p est lié. |
NEW(p, tag-field-value1' tag-field-value2, ... tag-field-valuen ) (procédure) |
Définit un enregistrement dynamique avec des variantes pointées par p. L'espace alloué aux champs de variante dépend des valeurs des champs de balise répertoriées. Les valeurs des champs de balise doivent être répertoriées dans l'ordre déclaré et la liste doit être contiguë. La première valeur de champ de balise doit correspondre au premier champ de balise déclaré, mais la dernière valeur de champ de balise de la liste ne doit pas nécessairement être le dernier champ de balise déclaré. |
DISPOSE(p) (procédure) |
Désalloue la variable allouée dynamiquement pointée par p. p conserve la même valeur, mais p^ devient indéfini. |
SIZEOF(p, tag-field-value1' tag-field-value2' ... tag-field-valuen ) (fonction) |
Renvoie la taille (en mots Cray) d'une variable dynamique : c'est-à-dire le nombre entier de mots qu'un appel à NEW alloue lorsqu'il est appelé avec la même liste de paramètres. SIZEOF prend un nombre variable de paramètres et fonctionne exactement comme NEW utilisé comme fonction. La valeur du pointeur p est renvoyée sans modification. |
La fonction SIZEOF est une extension CRI de la norme ISO niveau 1 Pascal.
Exemple :
Cet exemple déclare un type de pointeur nommé pntr et trois variables de pointeur nommées p1, p2 et first étant liées au type d'enregistrement nommé personnel. L'enregistrement lui-même contient une variable de pointeur nommée link. Le premier enregistrement est alloué dynamiquement de la manière suivante :
La première instruction alloue dynamiquement un enregistrement de type personnel et définit le pointeur pour qu'il pointe vers celui-ci. La deuxième instruction accède au champ de lien de cet enregistrement via le pointeur et lui attribue la valeur NIL. Un deuxième enregistrement peut être alloué dynamiquement et lié au premier comme suit :
- p2:=first;
- NEW(p1);
- p1^.link:=p2^.link;
- p2^.link:=p1;
La liste des enregistrements est liée par les champs de liaison. Les enregistrements sont ajoutés au milieu d'une telle liste en procédant comme suit :
- Déterminez l'enregistrement après lequel le nouvel enregistrement doit être ajouté, en parcourant la liste au moyen des pointeurs de champ de liaison.
- Définissez le pointeur p2 pour pointer vers cet enregistrement.
- Utilisez les instructions suivantes pour allouer et insérer dynamiquement le nouvel enregistrement :
- NEW(p1);
- p1^.link:=p2^.link;
- p2^.link:=p1;
Pour supprimer un enregistrement, le pointeur p2 est à nouveau défini pour pointer vers l'enregistrement précédant celui à supprimer. Les instructions suivantes suppriment l'enregistrement tout en conservant la liste dans l'ordre :
- p2^.link := p1^.link;
- DISPOSE(p1);
La deuxième forme de l'instruction NEW fonctionne de la même manière que la première, mais elle permet également de spécifier des valeurs de champ de balise pour les enregistrements variants.
Exemple :
Un enregistrement pour un employé actuellement actif et pleinement investi est attribué comme suit :
- NEW(p1, fullvest, FALSE);
Un enregistrement relatif à un employé retraité ayant acquis toutes ses droits est réaffecté comme suit :
- NEW(p1, fullvest, TRUE);
Un enregistrement comprenant les champs fmoney, yearvested et pension_montly_amt est alloué par l'instruction ci-dessus. La variante d'un enregistrement alloué par cette forme de l'instruction NEW ne peut pas être modifiée ultérieurement dans le programme. L'enregistrement ci-dessus, par exemple, ne peut pas être modifié ultérieurement pour contenir les champs désignés par la valeur de champ de balise partvest.
Si un enregistrement de variante est alloué dynamiquement par la première forme de l'instruction NEW (en ne spécifiant aucune valeur de champ de balise), suffisamment d'espace est alloué pour répondre aux exigences les plus importantes possibles.