LA GESTION DES ERREURS
Mots clés du BBC BASIC.
ERL : retourne le numéro de ligne où s'est produite la dernière erreur.
ERR : retourne le code de la dernière erreur relevée.
ERROR : force une erreur a se produire ou définit une erreur personnalisée.
ON ERROR : active un gestionnaire d'erreur général pour tout le programme.
ON ERROR LOCAL : active un gestionnaire d'erreur local dans un bloc d'instructions.
ON ERROR OFF : désactive le gestionnaire d'erreur général.
ON ERROR LOCAL OFF : désactive la gestion des erreur dans le bloc d'instruction.
REPORT : affiche la description de la dernière erreur survenue.
REPORT$ : retourne un STRING avec la description de la dernière erreur survenue.
RESTORE DATA : replace le pointeur de lecture des DATA à a position sauvegardée par LOCAL DATA.
RESTORE ERROR : restaure l'état de piégeage des erreurs enregistré par ON ERROR LOCAL.
RESTORE LOCAL : restaure les paramètres formels et les variables LOCAL / PRIVATE.
PRÉAMBULE.
Par défaut, le BBC BASIC stop l'exécution du programme si une erreur est détectée et affiche un message indiquant le type d'erreur retournée, ainsi que parfois le nom du module installé ou appelé dans lequel l'erreur s'est produite et/ou le numéro de ligne ou l'erreur est apparue, si le listing est numéroté.
Si ce comportement est très utile lors de la conception du programme, pour repérer et corriger les erreurs, il doit être proscrit lors de son utilisation pérenne future. Le programme devra alors prévoir un gestionnaire d'erreurs pour prévenir l'arrêt de l'application et s'assurer que de mauvaises manipulations de l'utilisateur, par exemple une division par 0, ou des interactions avec d'autres programmes, ne soient pas à l'origine d'une sortie prématurée du programme, faisant perdre les données en cours d'utilisation et provoquant une frustration de l'utilisateur.
Bien entendu, il serait préférable d'anticiper toutes les erreurs qui pourraient arriver durant l'exécution du programme, mais cela est le plus souvent impossible, tant les utilisateurs, systèmes et machine sont différentes et leur association imprévisible. C'est pour cela que, si vous prévoyez de distribuer votre programme, le piégeage des erreurs par un gestionnaire est indispensable pour assurer un certain confort en indiquant, à minima, dans un message, le type d'erreur et le moyen de la corriger.
TYPES DE GESTIONNAIRES D'ERREURS.
Pour initialiser un gestionnaire d'erreurs, le BBC BASIC for SDL 2.0 propose 2 instructions composées :
- ON ERROR action, pour créer un gestionnaire d'erreur général et pérenne ;
- ON ERROR LOCAL action, pour créer un gestionnaire d'erreur éphémère dans un bloc d'instruction.
action peut-être :
- une instruction unique telle que : une affectation ; PRINT ; END ; INPUT ; ... ;
- une suite d'instructions séparées par deux-points (:), par exemple : PRINT "Désolé, il y a une erreur." : END ;
- mais le plus souvent, l'appel d'une procédure ou d'une fonction personnalisée.
Quand une erreur sera détectée, action sera exécuté puis le programme reprendra à l'instruction suivant la ligne où se trouve le gestionnaire d'erreur ON ERROR ou ON ERROR LOCAL.
GESTIONNAIRE D'ERREUR GÉNÉRALE.
La forme ON ERROR action doit être utilisé dans le module principal du script, et en dehors de tout bloc d'instructions tel que des boucles FOR, REPEAT ou WHILE ou des définitions de procédures ou de fonctions personnalisées.
kdiviseur = 0
ktemoin = 5 : PRINT "ktemoin : " ; ktemoin
ON ERROR PRINT "erreur detectee !" : kdiviseur = 2
PRINT "ktemoin : " ; ktemoin
ktemoin = ktemoin + 1 : PRINT "ktemoin : " ; ktemoin
kdivision = ktemoin / kdiviseur
PRINT "kdivision : " ; kdivision
END
Note : le plus souvent, on dirigera la suite du programme vers une procédure personnalisée, spécialement rédigée pour tenter de corriger le plus possible d'erreurs potentielles.
Si plusieurs instructions composées ON ERROR sont présentent dans le script, c'est la dernière rencontrée par le programme qui est la seule qui sera prise en compte.
kdiviseur = 0
ON ERROR PRINT "erreur detectee !" : kdiviseur = 2
ON ERROR PRINT "Fin du programme !" : END
kdivision = ktemoin / kdiviseur
PRINT "kdivision : " ; kdivision
END
Contrairement à la forme ON ERROR LOCAL la pile des adresses de retour, permettant de retourner à l'entête d'une boucle d'instructions FOR, REPEAT ou WHILE est vidée. Donc, si le programme rencontre une instruction composée ON ERROR dans une boucle d'instructions et qu'une erreur est retournée dans cette boucle d'instructions, le programme recommencera à la suite de la ligne où se trouve l'instruction composée ON ERROR et retournera obligatoirement une nouvelle erreur en rencontrant une instruction de cloture de boucle NEXT, UNTIL ou ENDWHILE, car il ne saura pas où recommencer la boucle d'instructions correspondante, les adresses de retour étant toutes perdues.
kdiviseur = 0
ktemoin = 5
REPEAT
ON ERROR PRINT "erreur detectee !" : kdiviseur = 2
PRINT "ktemoin : " ; ktemoin
ktemoin = ktemoin + 1 : PRINT "ktemoin : " ; ktemoin
kdivision = ktemoin / kdiviseur
PRINT "kdivision : " ; kdivision
UNTIL kdivision <> 0
END
Cet exemple produira une boucle infinie, car bien que l'erreur "Division by zero" soit bien traitée, l'appel de l'instruction composée ON ERROR ayant détruit la pile des adresses de retour, une erreur "Not in a REPEAT loop" sera retournée chaque fois que le programme rencontrera l'instruction de cloture UNTIL kdivision <> 0. Et cela, même si le traitement de l'erreur était ON ERROR THEN EXIT REPEAT.
De plus si aucune erreur n'est détectée dans la boucle d'instructions, comme l'appel de l'instruction composée ON ERROR restera active, et si une erreur se produisait dans une autre partie du script, la suite du programme serait redirigé dans la boucle d'instructions où elle est présente, ce qui retournerait une erreur lors de la rencontre de l'instruction de cloture de la boucle d'instructions. Sauf si une instruction composée ON ERROR OFF est présente juste après la sortie.
kdiviseur = 0
REPEAT
ON ERROR PRINT "erreur detectee !" : kdiviseur = 2
PRINT "Dans la boucle REPEAT ..."
kdivision = 10 / 2
UNTIL TRUE
kdivision = 10 / kdiviseur
PRINT "Dans le module principal !"
END
GESTIONNAIRE D'ERREUR LOCALE.
La forme ON ERROR LOCAL action doit être utilisé dans les blocs d'instructions telle que des boucles FOR, REPEAT ou WHILE ou des définitions de procédures ou de fonctions personnalisées, et en dehors du module principal du programme.
La forme ON ERROR LOCAL préserve cette pile, permettant de retourner à l'entête d'une boucle d'instructions FOR, REPEAT ou WHILE est vidée. Donc, si le programme rencontre une instruction composée ON ERROR LOCAL dans une boucle d'instructions et qu'une erreur est retournée dans cette boucle d'instructions, le programme recommencera à la suite de la ligne où se trouve l'instruction composée ON ERROR LOCAL et, si aucune autre erreur n'est rencontrée, le programme saura à qu'elle entête correspond les instructions de cloture de boucle NEXT, UNTIL ou ENDWHILE, qu'il rencontrera par la suite.
kdiviseur = 0
ktemoin = 5
REPEAT
ON ERROR LOCAL PRINT "erreur detectee !" : kdiviseur = 2
PRINT "ktemoin : " ; ktemoin
ktemoin = ktemoin + 1 : PRINT "ktemoin : " ; ktemoin
kdivision = ktemoin / kdiviseur
PRINT "kdivision : " ; kdivision
UNTIL kdivision <> 0
END
Note : les variables qui ont vu leur valeur modifié entre l'instruction composée ON ERROR LOCAL et l'erreur rencontrée, garderont leur dernière affectation. Il faudra parfois penser à réaffecter des valeurs d'entrée dans la boucle d'instruction à certaines variables pour le bon déroulement futur du programme.
Note : dans les définitions des procédures et les fonctions personnalisées, l'instruction composée ON ERROR LOCAL doit toujours être placée après l'instruction PRIVATE.
Contrairement à la forme ON ERROR qui perdure durant tout le programme, sauf si une instruction composée ON ERROR OFF est rencontrée, un gestionnaire d'erreur défini avec ON ERROR LOCAL sera détruit à la sortie du bloc d'instructions où il est présent.
kdiviseur = 0
REPEAT
ON ERROR LOCAL PRINT "erreur detectee !" : kdiviseur = 2
PRINT "resultat : " ; 10 / kdivision : REM - cette erreur /0 sera bien gérée par le gestionnaire d'erreur
UNTIL kdivision <> 0
kdiviseur = 0
REPEAT
PRINT "resultat : " ; 10 / kdivision : REM - cette erreur /0 ne sera pas gérée et arretera le programme
UNTIL kdivision <> 0
END
Il est possible de désactiver un gestionnaire d'erreur local avec l'instruction composée ON ERROR LOCAL OFF, et ce sera le gestionnaire d'erreur général, activé avec l'instruction composée ON ERROR, s'il existe, qui prendra en charge les traitements des erreurs. L'instruction composée ON ERROR LOCAL OFF ne désactive que le gestionnaire d'erreur pour le bloc d'instructions en cours. Si celui-ci se trouve imbriqué dans un autre et que ce parent possède lui aussi un gestionnaire d'erreur, il sera prioritaire sur le gestionnaire d'erreur général à la sortie du blocs d'instructions de son enfant.
ON ERROR LOCAL est utilisé dans la définition d'une procédure ou d'une fonction personnalisée, ou un bloc d'instructions, le gestionnaire d'erreur précédent, qui peut être un aussi un ON ERROR LOCAL présent d'un le bloc d'instructions parent, est automatiquement restauré à la sortie de la structure.
Bien que ce ne soit pas sa vocation première, l'instruction composée ON ERROR LOCAL peut être utilisé dans le module principal du programme, pour préserver la pile d'adresse de retour. Mais dans ce cas, il faudra restaurer manuellement le gestionnaire d'erreur général avec une instruction composée RESTORE ERROR. En effet, RESTORE ERROR restaure le gestionnaire d'erreur antérieur à la dernière instruction composée ON ERROR LOCAL rencontrée.
Note : l'instruction composée RESTORE LOCAL, qui ne peut être présent que dans la définition d'une procédure ou d'une fonction personnalisée, permet de restaurer les valeurs des paramètres formels, passées à la procédure ou à la fonction lors de son appel, ainsi que celle des variables LOCAL et/ou PRIVATE à leur valeur initiale. RESTORE LOCAL exécute également les instructions composées RESTORE DATA et RESTORE ERROR. RESTORE LOCAL est principalement destinée à être utilisée dans un gestionnaire d'erreurs ON ERROR LOCAL.
CRÉER UN RAPPORT D'ERREUR.
Pour mieux gérer les erreurs lors de l'exécution d'une application et pour tenter d'éviter son arrêt définitif, BBC BASIC for SDL 2.0 offre plusieurs instructions permettant de connaitre le type d'erreur rencontrée afin de proposer une résolution adaptée.
L'instruction ERL retournera le numéro de la ligne :
- où s'est produite l'erreur à traitée si elle a été interceptée dans le module principal, ou dans un de ses blocs d'instruction ;
- qui a appelé la procédure ou fonction où l'erreur a été interceptée, et non celle où s'est réellement produite l'erreur ;
- contenant l'instruction DATA fautive, et non l'instruction READ qui a tenté de lire cette donnée.
10 ON ERROR PRINT ERL : END
20 PRINT 10 / 0
retourne : 20
Si le script n'est pas numéroté, l'instruction ERL retournera 0.
ON ERROR PRINT ERL : END
PRINT 10 / 0
retourne : 0
L'instruction ERR retournera le numéro désignant le type de l'erreur qui a été interceptée.
ON ERROR PRINT ERR : END
PRINT 10 / 0
retourne : 18
L'instruction REPORT affichera une description de l'erreur, mais retourne une chaine de caractères vide.
ON ERROR REPORT : END
PRINT 10 / 0
retourne : Division by zero
L'instruction REPORT$ retournera dans une chaine de caractères une description de l'erreur sans l'afficher.
ON ERROR kerreur$ = REPORT$ : PRINT kerreur$ : END
PRINT 10 / 0
retourne : Division by zero
RUBRIQUE.
Liste des erreurs pour plus de détails sur la nature des différentes erreurs retournées en BBC BASIC for SDL 2.0.
Votre aide est précieuse pour améliorer ce site, alors n'hésitez pas à faire part de
Dans la RETROGICIEL vous trouvez des suggestions simples et classiques pour
TESTER - DÉCOUVRIR - PRATIQUER - APPROFONDIR - EXPLORER
avec un exemple de résolution à télécharger pour vous inspirer.