Aller au contenu

MCH3601

Pointeur non défini pour position mémoire référencée.

Gravité 40 · Fin anormale du programme ou de la fonction

Comment s'en sortir

Le programme a utilisé un pointeur qui ne pointe sur rien. En pratique, c'est presque toujours un paramètre : le programme lit un paramètre que l'appelant ne lui a pas transmis.

Les causes les plus fréquentes

  • Un paramètre manquant à l'appel. Le programme attend 3 paramètres, l'appelant (un CL, un autre programme, un CALL tapé à la main) n'en passe que 2. Le troisième n'a pas d'adresse : dès qu'on le lit, MCH3601.
  • Un paramètre facultatif lu sans vérification : déclaré OPTIONS(*NOPASS) ou *OMIT, mais utilisé sans tester qu'il a bien été passé.
  • Une variable basée (BASED(ptr)) utilisée alors que son pointeur vaut encore *NULL, ou pointe sur une mémoire libérée (DEALLOC, fin de procédure).

Diagnostiquer

Dans l'historique du travail, MCH3601 est suivi en RPG ILE de RNQ0222 (erreur de pointeur ou de paramètre), avec le programme et le numéro d'instruction. Comparez ensuite l'appel et la déclaration des paramètres, un par un.

/* Le message complet, avec le programme et l'instruction en cause */
DSPJOBLOG

Corriger

Passez tous les paramètres attendus, dans le bon ordre. Pour un paramètre facultatif, testez sa présence avant de le lire :

dcl-pi *n;
  client  char(10);
  option  char(1) options(*nopass);
end-pi;

dcl-s choix char(1) inz('N');

if %parms() >= %parmnum(option);   // le paramètre a-t-il été passé ?
  choix = option;
endif;

Appelez vos programmes et procédures RPG par un prototype (CALLP) plutôt que par CALL : le compilateur vérifie alors le nombre et le type des paramètres.

Un programme peut fonctionner des mois malgré un paramètre manquant, parce que la mémoire pointait par hasard sur quelque chose de lisible. Le jour où il plante, ce n'est pas le programme qui a changé : c'est son appelant, ou l'état de la mémoire. Cherchez l'appel, pas une modification récente du programme.

Ce que dit IBM

Cause

Un pointeur a été utilisé soit directement, soit comme pointeur de base pour lequel aucune adresse n'a été définie.

Sur votre IBM i

Afficher la description complète du message :

DSPMSGD RANGE(MCH3601) MSGF(QSYS/QCPFMSG)

L'intercepter dans un programme CL, quand il est envoyé comme message d'échappement :

MONMSG MSGID(MCH3601) EXEC(DO)
  /* traitement de l'erreur */
ENDDO