Le traitement des erreurs

Jean-Michel Doudoux

- Titre : Le traitement des erreurs

- Auteur : Jean-Michel Doudoux

- Parution : 6 novembre 2003

- Mise à jour : 24 décembre 2019

- Licence : Copyright ® 2003 J.M.Doudoux. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.

Sommaire

- Avant-propos

- I. La classe Exception

- II. Les routines de traitements des erreurs

- III. Lever une exception

- IV. Les exceptions dans l'environnement d'exécution

- V. Les exceptions silencieuses

Avant-propos

Une exception est un événement qui survient lors d'une erreur à l'exécution du programme. La VCL fournit un ensemble de classes dérivant toutes de la classe Exception dans l'unité SysUtils qui représente les exceptions prédéfinies.

I - La classe Exception

Les exceptions sont des classes qui ne comportent que quelques champs qui permettent d'identifier l'exception. Certaines exceptions possèdent des champs supplémentaires qui permettent de connaitre avec plus de précision l'origine de l'erreur.

La propriété Message contient le message qui est affiché quand l'exception est levée.
La propriété HelpContext permet de faire la liaison entre l'exception et une rubrique du fichier d'aide.

La classe Exception propose plusieurs constructeurs :

- le constructeur Create permet de créer l'exception et de lui associer le message passé en paramètre ;

- le constructeur CreateFmt permet de créer l'exception et de formater le message passé en paramètre avec la chaine de formatage et le tableau d'arguments ;

- le constructeur CreateRes permet de créer l'exception et de lui associer le message contenu dans le tableau de ressources à l'indice indiqué.

Les autres constructeurs ont les mêmes fonctionnalités, mais permettent en plus de préciser la propriété HelpContext.

Il n'est pas nécessaire de se préoccuper de la destruction des objets exceptions, car ils seront détruits par le gestionnaire d'exception.

Les principes d'héritage permettent de gérer plusieurs exceptions en même temps si celles-ci dérivent d'une même classe parent, voire de la classe mère de toutes les exceptions : la classe Exception.

Il est aussi possible de créer ses propres exceptions en dérivant une classe de la classe Exception ou d'une de ces classes filles.
Exemple :

type
Emon_erreur = class(Exception)
end;

Il est possible de rajouter des propriétés (pour détailler l'exception) et des méthodes à ces nouvelles classes (par exemple de nouveaux entrepreneurs pour alimenter les nouvelles propriétés).

II - Les routines de traitements des erreurs

Le Pascal objet définit trois opérateurs pour gérer la capture des exceptions : try, except et finally.

Ils sont regroupés en deux structures : try … except … end et try … finally … end .

Le mot try est suivi des traitements qui doivent être protégés, car ils sont susceptibles de soulever une exception. Si une exception est levée dans ces traitements, le programme exécute les instructions incluses après le mot except ou finally.

Dans le bloc except, il faut tester la ou les exceptions concernées et leur associer les traitements qui conviennent.

Dans le bloc except, les mots clés on .. do permettent de tester le type d'exception qui est levée et d'y associer les traitements. La syntaxe de on .. do ressemble à celle de l'instruction case. Il est possible de traiter plusieurs exceptions de la même façon en les séparant par des points-virgules. Il peut y avoir plusieurs instructions on avec des exceptions différentes : elles seront évaluées dans un ordre séquentiel. Il est donc important de préciser les exceptions dans l'ordre inverse de la hiérarchie de classe Exception : les classes filles avant les classes mères.

À la fin du bloc except, il est possible de définir un branchement else qui englobe toutes les autres exceptions non capturées dans le bloc.

try
...
except
on e1 : type_exception1 do instruction ou bloc_d'instructions
on e2 : type_exception2 do instruction ou bloc_d'instructions
...
else instruction ou bloc_d'instructions
end;

Exemple :

try
...
except
on EInOutError do ...
else ...
end;

Il est possible de fournir un nom à l'exception pour accéder à l'instance de celle-ci.
Exemple :

try
...
Except
on e : Emon_erreur do begin
...
end;
end;

Il est alors possible d'accéder aux champs et aux méthodes de cette instance.

Pour accéder à l'instance de l'exception, il est aussi possible d'appeler la fonction ExceptObject définie dans l'unité SysUtils qui renvoie l'instance de l'exception courante. Cette instance est référencée sous la forme d'un objet TObject qu'il faut convertir à l'aide de l'instruction as. Le bloc inclus après finally est toujours exécuté qu'une exception soit levée ou non : il permet notamment de libérer des ressources qui ont été allouées.

Il n'est pas possible de faire suivre un bloc try par une instruction except et finally. Il faut emboiter deux blocs try, l'un contenant except et l'autre contenant finally.

le bloc try … finally ne gère pas l'exception donc elle ne libère pas les ressources qui lui sont allouées. L'exception continue de se propager jusqu'à ce qu'elle rencontre un bloc de type try … except ou le gestionnaire d'exception par défaut qui contient un tel bloc.

Les blocs except et finally sont facultatifs.

Dès qu'une exception est levée, le programme recherche dans la pile de fonctions en cours une fonction qui contient un gestionnaire d'exception. Une exception levée est propagée dans les procédures et fonctions en remontant les différents appels jusqu'à ce qu'elle soit capturée dans un bloc except. À ce moment, la propagation de l'exception s'arrête. Le reste du code de chaque fonction est ignoré.

Une fois l'exception traitée, le programme se poursuit après le bloc de gestion d'exception et non après l'instruction qui a provoqué l'exception.

Si l'exception n'est pas capturée en remontant la hiérarchie des procédures, elle est traitée par la méthode HandeException de l'objet Application qui définit un comportement par défaut. Il est possible de redéfinir cette méthode pour en modifier le comportement : par exemple ajouter un message dans un fichier log qui contiendra les exceptions levées.

III - Lever une exception

Le mot clé raise permet de lever une exception : cette instruction doit être suivie d'une instance d'une classe exception.

Exemple :

raise Emon_erreur.Create('Problème lors de l''exécution');

Raise permet aussi de relever une exception qui vient d'être capturée pour poursuivre sa propagation. Pour cela il suffit d'invoquer raise dans le bloc except.

Exemple :

try
...
Except
on EInOutError do
begin
... //traitement de l'exception
raise; // l'exception est relevée et donc passée à la procédure appelante
end;
end;

Il est possible de préciser au moment de l'appel à raise l'adresse qui est à l'origine de l'exception.

Exemple :

raise OutOfMemory at ReturnAddr;

IV - Les exceptions dans l'environnement d'exécution

Par défaut, lors de l'exécution d'un programme, dès qu'une exception est levée, le programme est interrompu à la ligne de l'instruction qui a levé l'exception et le message de l'exception est affiché. Il est alors possible de poursuivre directement ou pas à pas l'exécution. Cette option peut être désactivée en décochant l'option « arrêt sur les exceptions » dans la boite de dialogue options d'environnement.

L'objet application généré dans tous projets Delphi possède un mécanisme de gestion des exceptions par défaut : cet objet déclenche l'événement OnException dès qu'une exception lui arrive. Si aucun gestionnaire d'exception ne capture l'exception, l'objet application exécute sa méthode HandleException qui appelle elle-même la fonction précisée par la propriété OnException. Cette propriété doit recevoir une méthode qui respecte le type TExceptionEvent

TExceptionEvent = procédure(Sender : TObject ; E : Exception) of Object;

Exemple :

procedure TForm1.gestion_erreur(Sender : TObject ; E : Exception);
begin
MessageDlg(E.message,mtInformation,[mrOk],0);
end;

procédure TForm1.FormCreate(Sender: TObject);
begin
// affectation du gestionnaire d'exception
Application.OnException:=gestion_erreur;
end;

V - Les exceptions silencieuses

Ce sont des exceptions qui dérivent de la classe EAbort. La différence avec une exception normale est qu'elles ne remontent pas les différents niveaux de la pile et ne dépassent pas le premier niveau. Si une telle exception n'est pas traitée à ce moment-là, elle est détruite.