%ALLOC
Réserver de la mémoire
Réserve un bloc de mémoire de la taille demandée, en octets, et renvoie un pointeur sur son début.
Syntaxe
%ALLOC(taille)
taille- Le nombre d'octets à réserver, sous forme d'une expression numérique entière.
- Résultat
- Un pointeur sur le début de la mémoire réservée.
À quoi ça sert
Un tableau déclaré avec dim(1000) occupe toujours 1000 éléments, même si on n'en utilise que trois. Avec %ALLOC, on ne prend que la place nécessaire, en fonction de ce qu'on découvre à l'exécution (nombre de lignes lues, longueur d'un texte).
On déclare le tableau ou la structure avec based(pointeur), on affecte le résultat de %ALLOC au pointeur, puis on utilise la zone comme d'habitude. Tout bloc réservé doit être rendu avec dealloc.
Exemple 1 : Un tableau à la bonne taille
**free
// %ALLOC : reserver de la memoire au moment de l'execution, puis la rendre.
ctl-opt dftactgrp(*no) actgrp(*new);
dcl-s p pointer;
dcl-s villes char(12) dim(50) based(p);
dcl-s nb int(10) inz(4);
dcl-s i int(10);
// On reserve exactement la place de 4 villes (4 x 12 octets).
p = %alloc(nb * %size(villes(1)));
snd-msg 'Memoire reservee : ' + %char(nb * %size(villes(1))) + ' octets';
villes(1) = 'Montpellier';
villes(2) = 'Lyon';
villes(3) = 'Brest';
villes(4) = 'Nantes';
for i = 1 to nb;
snd-msg 'Ville ' + %char(i) + ' : [' + villes(i) + ']';
endfor;
// dealloc(n) rend la memoire ET remet le pointeur a *NULL.
dealloc(n) p;
snd-msg 'Pointeur nul apres liberation ? ' + %char(p = *null);
*inlr = *on;
Résultat réel, compilé et exécuté sur IBM i 7.5 :
Memoire reservee : 48 octets
Ville 1 : [Montpellier ]
Ville 2 : [Lyon ]
Ville 3 : [Brest ]
Ville 4 : [Nantes ]
Pointeur nul apres liberation ? 1
Le tableau est déclaré pour 50 villes, mais on n'en réserve que 4 : 48 octets. dealloc(n) p rend la mémoire et remet le pointeur à *NULL, ce que confirme la dernière ligne.
Exemple 2 : Une demande trop grosse
**free
// %ALLOC : que se passe-t-il quand la demande est trop grosse ?
ctl-opt dftactgrp(*no) actgrp(*new);
dcl-ds sds psds qualified;
msgid char(7) pos(40);
msgtxt char(80) pos(91);
end-ds;
dcl-s p pointer;
dcl-s taille int(10);
monitor;
taille = 1000000;
p = %alloc(taille);
snd-msg '1 Mo : reservation reussie';
dealloc(n) p;
taille = 20000000;
p = %alloc(taille);
snd-msg '20 Mo : reservation reussie';
dealloc(n) p;
on-error;
snd-msg 'Echec : ' + sds.msgid + ' ' + %trim(sds.msgtxt);
endmon;
*inlr = *on;
Résultat réel, compilé et exécuté sur IBM i 7.5 :
1 Mo : reservation reussie
Echec : RNX0425 La longueur demandée pour l'allocation de mémoire est hors limites.
1 Mo passe, 20 Mo échoue avec RNX0425 (longueur demandée hors limites). Le programme rattrape l'erreur avec monitor.
Exemple 3 : Le même programme avec alloc(*teraspace)
**free
// %ALLOC : avec alloc(*teraspace), la meme demande de 20 Mo reussit.
ctl-opt dftactgrp(*no) actgrp(*new) alloc(*teraspace);
dcl-ds sds psds qualified;
msgid char(7) pos(40);
msgtxt char(80) pos(91);
end-ds;
dcl-s p pointer;
dcl-s taille int(10);
monitor;
taille = 1000000;
p = %alloc(taille);
snd-msg '1 Mo : reservation reussie';
dealloc(n) p;
taille = 20000000;
p = %alloc(taille);
snd-msg '20 Mo : reservation reussie';
dealloc(n) p;
on-error;
snd-msg 'Echec : ' + sds.msgid + ' ' + %trim(sds.msgtxt);
endmon;
*inlr = *on;
Résultat réel, compilé et exécuté sur IBM i 7.5 :
1 Mo : reservation reussie
20 Mo : reservation reussie
Avec le mot-clé alloc(*teraspace) dans ctl-opt, la même réservation de 20 Mo réussit.
Le piège
Par défaut, les gros blocs sont refusés. Une demande de 20 Mo échoue avec l'erreur RNX0425 à l'exécution (exemple 2), alors que 1 Mo passe. Le mot-clé alloc(*teraspace) de ctl-opt permet la même demande (exemple 3).
N'oubliez jamais dealloc : un bloc non rendu reste réservé. Le tableau based de l'exemple 1 déclare 50 éléments alors que 4 seulement sont réservés : c'est à vous de ne pas dépasser.