Instruction RPG full free · IBM i (AS/400) · Données et calculs
DEALLOC
Libérer de la mémoire allouée
Rend au système une zone mémoire obtenue avec %ALLOC, pour qu'elle puisse être réutilisée.
Syntaxe
DEALLOC pointeur;
DEALLOC(N) pointeur;
DEALLOC(E) pointeur;
pointeur- Le pointeur reçu de l'allocation (%ALLOC).
(N)- Après la libération, met le pointeur à
*NULL. À préférer. (E)- Intercepte l'erreur : elle est signalée par %ERROR au lieu d'arrêter le programme.
- Effet
- La zone est libérée. Sans
(N), le pointeur garde son ancienne adresse ; avec(N), il vaut*NULL. Libérer une seconde fois une adresse déjà libérée lève RNQ0426.
À quoi ça sert
La mémoire que vous demandez avec %ALLOC reste réservée tant que vous ne la rendez pas. Dans un service qui tourne longtemps ou une boucle qui réserve à chaque tour, cela fait grossir le travail et finit en erreur de mémoire.
DEALLOC la rend. On l'utilise toujours avec (N), ce qui évite de garder un pointeur vers une zone qui n'est plus à nous.
Exemple 1 : DEALLOC(N)
**free
// DEALLOC : liberer une zone obtenue par %alloc ou ALLOC.
ctl-opt dftactgrp(*no) actgrp(*new);
dcl-s ptr pointer;
dcl-s texte char(20) based(ptr);
ptr = %alloc(%size(texte));
texte = 'Dupont SA';
snd-msg 'Alloue : [' + %trim(texte) + '] nul=' + %char(ptr = *null);
dealloc(n) ptr;
snd-msg 'Apres (N) : nul=' + %char(ptr = *null);
dealloc(n) ptr;
snd-msg 'Second appel (N) sans erreur';
*inlr = *on;
Résultat réel, compilé et exécuté sur IBM i 7.5 :
Alloue : [Dupont SA] nul=0
Apres (N) : nul=1
Second appel (N) sans erreur
Une zone de 20 caractères est allouée, remplie, puis libérée avec DEALLOC(N) : le pointeur vaut *NULL après l'opération. Un second DEALLOC(N) sur ce pointeur nul ne provoque aucune erreur.
Exemple 2 : DEALLOC sans (N)
**free
// DEALLOC sans (N) : le pointeur reste renseigne, le second appel echoue.
ctl-opt dftactgrp(*no) actgrp(*new);
dcl-s ptr pointer;
dcl-s texte char(20) based(ptr);
ptr = %alloc(%size(texte));
texte = 'Martin et fils';
dealloc ptr;
snd-msg 'Apres dealloc : nul=' + %char(ptr = *null);
dealloc ptr;
snd-msg 'Cette ligne n est pas atteinte';
*inlr = *on;
Résultat réel, compilé et exécuté sur IBM i 7.5 :
Apres dealloc : nul=0
Erreur : RNQ0426 - (C G D F) Erreur lors d'une opération de gestion de mémoire.
Le premier DEALLOC réussit, mais le pointeur n'est pas nul : le test ptr = *null vaut faux. Le second DEALLOC sur cette adresse déjà libérée arrête le programme sur RNQ0426.
Le piège
Sans (N), le pointeur reste « vivant » alors que la mémoire est rendue. Dans le deuxième exemple, après le premier DEALLOC, ptr = *null est faux : rien n'empêche de réutiliser le pointeur, d'écrire dans la zone libérée, ou de la libérer deux fois (RNQ0426).
Prenez l'habitude d'écrire DEALLOC(N) : le pointeur est annulé et le second appel, comme dans le premier exemple, est sans effet. Un test if ptr <> *null évite alors toute erreur.