%REALLOC
Redimensionner un bloc de mémoire
Change la taille d'un bloc de mémoire déjà réservé, en conservant son contenu, et renvoie le pointeur à utiliser ensuite.
Syntaxe
%REALLOC(pointeur : taille)
pointeur- Le pointeur renvoyé par un précédent
%ALLOCou%REALLOC. taille- La nouvelle taille du bloc, en octets.
- Résultat
- Un pointeur sur le bloc redimensionné. Il peut être différent de l'ancien : il faut toujours utiliser la valeur renvoyée.
À quoi ça sert
Quand on lit un nombre inconnu de lignes, on démarre avec un petit bloc et on l'agrandit au fur et à mesure. %REALLOC garde les données déjà présentes, sans les recopier à la main.
Exemple 1 : Agrandir puis réduire
**free
// %REALLOC : agrandir une zone deja reservee sans perdre son contenu.
ctl-opt dftactgrp(*no) actgrp(*new);
dcl-s p pointer;
dcl-s ancien pointer;
dcl-s villes char(12) dim(50) based(p);
dcl-s nb int(10);
dcl-s i int(10);
// Au depart, place pour 2 villes.
nb = 2;
p = %alloc(nb * %size(villes(1)));
villes(1) = 'Montpellier';
villes(2) = 'Lyon';
// Il en faut 4 : on agrandit, les 2 premieres restent en place.
nb = 4;
ancien = p;
p = %realloc(p : nb * %size(villes(1)));
snd-msg 'Adresse changee ? ' + %char(p <> ancien);
villes(3) = 'Brest';
villes(4) = 'Nantes';
for i = 1 to nb;
snd-msg 'Ville ' + %char(i) + ' : [' + villes(i) + ']';
endfor;
// On reduit a 1 ville : seule la premiere est conservee.
nb = 1;
p = %realloc(p : nb * %size(villes(1)));
snd-msg 'Apres reduction : [' + villes(1) + ']';
dealloc(n) p;
*inlr = *on;
Résultat réel, compilé et exécuté sur IBM i 7.5 :
Adresse changee ? 1
Ville 1 : [Montpellier ]
Ville 2 : [Lyon ]
Ville 3 : [Brest ]
Ville 4 : [Nantes ]
Apres reduction : [Montpellier ]
Le bloc démarre à 2 villes et passe à 4 : Montpellier et Lyon sont toujours là, on ajoute Brest et Nantes. La ligne « Adresse changee ? » vaut 1 : le bloc agrandi a été déplacé. En réduisant à 1 ville, seule la première est conservée.
Exemple 2 : Partir d'un pointeur nul
**free
// %REALLOC : un pointeur nul donne une premiere reservation, comme %ALLOC.
ctl-opt dftactgrp(*no) actgrp(*new);
dcl-s p pointer;
dcl-s note char(20) based(p);
snd-msg 'Avant : pointeur nul ? ' + %char(p = *null);
p = %realloc(p : %size(note));
snd-msg 'Apres : pointeur nul ? ' + %char(p = *null);
note = 'Reservation';
snd-msg 'Contenu : [' + note + ']';
dealloc(n) p;
*inlr = *on;
Résultat réel, compilé et exécuté sur IBM i 7.5 :
Avant : pointeur nul ? 1
Erreur : RNQ0426 - (C G D F) Erreur lors d'une opération de gestion de mémoire.
Un pointeur nul n'est pas accepté : le programme s'arrête avec RNQ0426, erreur de gestion de mémoire.
Le piège
Le pointeur de départ doit venir de %ALLOC. Avec un pointeur nul, %REALLOC ne réserve rien et s'arrête avec RNQ0426 (exemple 2). Pour la première réservation, utilisez %ALLOC.
Réaffectez toujours le résultat au pointeur (p = %realloc(p : ...)) : l'adresse du bloc change (exemple 1), et l'ancienne ne doit plus servir.