|
|
|
|
![]() ![]() |
Nov 15 2004, 08:27 PM
Post
#1
|
|
|
Newbie [Level 2] ![]() ![]() Group: Members Posts: 25 Joined: 15-November 04 Member No.: 2,296 |
Gestion des exceptions sous Delphi
1. Introduction En tant que programmeur Delphi (ou une autre language orienté objet), vous avez été ou serez amenés à rencontrer des exceptions. En programmation, il est difficile et alourdissant pour le code de contrôler toutes les valeurs renvoyées par les fonctions, les entrées utilisateurs, ... Heureusement, le language (le pascal objet) nous informe des erreurs et interrompt le programme et affiche un message descriptif de l'erreur. Dans ce cas, comme on a une erreur et que par conséquent les données sont incertaines, le programme n'exécute pas la fin de la procédure (ou fonction, ...) en cours. Le but de cette page est de pouvoir gérer ces exceptions afin de modifier le comportement du programme sans pour autant l'arrêter. 2. Le bloc TRY .. EXCEPT Le bloc TRY EXCEPT offre au programmeur la possibilité d'exécuter un bloc d'instructions dans le cas d'une erreur d'exception. Voici un exemple simple: function Diviser(a,b:integer):integer; begin try result := a div b; except result := 0;//Si on a une division par 0, //on force le résultat à 0 end; end; Exemple 1 : la gestion d'une erreur de division par zéro par un bloc TRY .. EXCEPT Cette fonction gère donc ainsi la division par zéro en remplaçant le résultat par 0 dans le cas d'une exception. Les instructions contenues entre EXCEPT et END (result := 0; dans ce cas-ci) ne sont exécutées que si une exception a été générée dans le bloc d'instructions contenu entre le TRY et le EXCEPT (dans ce cas-ci: result := a div b;). Ceci évite donc un message d'erreur en mode exécution en stand-alone , le message d'exception étant quand même affiché en mode exécution sous environnement Delphi. Dans ce cas-ci, on ne protège qu'une ligne de code, voici maintenant un autre exemple avec plusieurs lignes protégées par un TRY .. EXCEPT (on considère a et b comme integer): try a := StrToInt(edit1.text);//Ici, on peut tomber sur //des valeurs bizarres (lettres) dans le TEdit b := b div a; //Ici, on peut avoir une division par 0 except on EConvertError do ShowMessage('La valeur entrée est incorrecte!'); on EDivByZero do ShowMessage('Vous avez entré une valeur nulle!'); end; Exemple 2 : Traiter plusieurs exceptions dans le même bloc Remarquez que pour définir un bloc de plusieurs ligne entre un TRY et un EXCEPT, aucun begin n'est nécessaire (pareil entre EXCEPT et son END). Dans l'exemple, on remarque qu'il y a deux raisons possibles pour qu'une exception soit générée: un mauvais paramètre pour la fonction StrToInt ou bien une division par 0. Il est donc nécessaire de pouvoir savoir laquelle nous a fait entrer dans le bloc EXCEPT. Ceci est possible grâce à la formule: on Nom de l'exception do Bloc d'instructions; Deux exemples concrets afin de comparer une programmation avec et une sans gestion des exceptions: Exemple 3 : Sans gestion des exceptions Exemple 4 : Avec gestion des exceptions var a,b : integer; b := 0; ShowMessage('Message 1'); a := a div b; ShowMessage(inttostr(a)); ShowMessage('Message 2'); var a,b : integer; try b := 0; ShowMessage('Message 1'); a := a div b; ShowMessage(inttostr(a)); except ShowMessage( 'Vous avez effectué une division par zéro!'); end; Résultat affiché: Résultat affiché: 3. Le bloc TRY .. FINALLY Contrairement à EXCEPT qui délimite les instructions à exécuter en cas d'exception, FINALLY force le programme à exécuter les lignes de son bloc dans tous les cas (exception ou pas). var a : integer; try a := StrToInt(edit1.text);//Ici, on peut tomber sur des //valeurs bizarres (lettres) dans le TEdit finally ShowMessage('Erreur ou pas, ce message doit être affiché'); end; Exemple 5 : Une utilisation simple du bloc TRY .. FINALLY L'exemple est assez inutile dans ce cas-ci, mais il vous montre que qu'il y ait une exception ou pas, on peut exécuter un bloc d'instructions. Un exemple plus significatif de l'utilité d'un try .. finally me vient à l'esprit: Soit un programme qui doit lire un fichier qui contient 10 valeurs, une par ligne et en afficher la somme. Si vous n'utilisez pas de TRY .. FINALLY, votre code ressemblera à ceci: function Somme(NomFichier:String):integer; var fic : TextFile; Nombre, i : integer; begin result:=0; AssignFile(fic, NomFichier); reset(fic); for i := 1 to 10 do begin ReadLn(Nombre); result:=result+Nombre; end; closeFile(fic); end; Exemple 6 : Lecture de fichier sans gestion des exceptions Ce code fonctionnera parfaitement dans les conditions idéales. Mais imaginons maintenant que le fichier ne contienne que 5 nombres: on aura un message d'erreur qui indiquera une lecture au-delà de la fin de fichier et le programme passera la fin de la fonction sans exécuter les dernières lignes qui contiennent pourtant une ligne très importante: le CloseFile. Ce qui veut dire que le fichier est toujours ouvert et que le programme ne saura plus y accéder... Voici maintenant le code modifié pour parer à cette erreur éventuelle: function Somme(NomFichier:String):integer; var fic : TextFile; Nombre, i : integer; begin result:=0; AssignFile(fic, NomFichier); reset(fic); try for i := 1 to 10 do begin ReadLn(Nombre); result:=result+Nombre; end; finally closeFile(fic); end; end; Exemple 7 : Lecture de fichier avec gestion des exceptions Dans ce cas-ci, le fichier sera fermé lorsque la fonction est terminée, qu'il y ait rencontré une erreur ou pas. Remarquez que les blocs TRY .. FINALLY ne suppriment pas les messages d'erreurs comme les font les blocs TRY .. EXCEPT. Les blocs TRY .. FINALLY sont aussi beaucoup utilisés pour libérer une instance d'objet qui a une durée de vie limitée à une fonction (ou procedure) avant de quitter cette fonction (ou procedure). 4. Utiliser les 2 blocs imbiqués Il est parfois nécessaire d'utiliser un bloc TRY .. EXCEPT à l'intérieur d'un autre bloc TRY .. FINALLY Reprenons l'exemple précédent: on veut que la fonction renvoie 0 si elle a rencontré une erreur et on ne veut surtout pas de message d'erreur. Le code sera donc le suivant: function Somme(NomFichier:String):integer; var fic : TextFile; Nombre, i : integer; begin result:=0; AssignFile(fic, NomFichier); reset(fic); try try for i := 1 to 10 do begin ReadLn(Nombre); result:=result+Nombre; end except result:=0; end finally closeFile(fic); end; end; Exemple 8 : Imbrication d'un bloc TRY .. EXCEPT dans un bloc TRY .. FINALLY 5. Générer une exception Vous pouvez évidemment créer vos propres exceptions pour prévenir des erreurs par exemple dans l'utilisation des composants que vous distribuez. La déclaration en est simple: type EMonException = class(Exception); Et maintenant pour la générer: raise EMonException.Create('Ceci est mon exception'); Vous remarquerez qu'on appelle la méthode Create et qu'on ne libère pas l'objet. En fait, l'objet exception est libéré automatiquement par le gestionnaire d'exception. 6. Conclusion Les exceptions sont des armes puissantes qui optimiseront la stabilité de vos applications. De leur utilisation va dépendre la qualité de vos programmes. Elles leur donnent aussi un aspect plus professionnel en personnalisant les messages d'erreur et en les rendant plus explicites et plus compréhensibles pour l'utilisateur. 7. Remarque Par défaut, Delphi s'arrête sur toutes les exceptions lorsque l'application est lancée à partir de l'environnement de conception. Ceci permet de se rendre compte des exceptions générées et de mieux les cibler. Pour se mettre en situation réelle (telle que l'utilisateur le verra), vous avez 2 possibilités: * Vous compilez votre programme et l'exécutez à partir de l'explorateur * Vous pouvez désactiver les exceptions dans le menu Options du debugger du menu Outils 8. Remerciements Je voudrais remercier les auteurs de * Lore's source converter, un puissant convertisseur de source Delphi/C++/Java vers HTML. (gratuit et open-source) * FirstPage 2000, un formidable éditeur HTML très complet. (gratuit) Grand merci à Michel qui rassemble toute cette communauté de développeurs et toutes ces portions de code si précieux. 8. Contacts/Auteur Actuellement développeur pour Electronic Design, je programme des applications PC et microprocesseurs pour les domaines de la parlophonie, téléphonie, domotique et systèmes d'appels. Pour tout contact, vous pouvez m'envoyer un mail, je suis égalemnt sur icq sous l'UIN 30687888. Marchioni Valérian, le 12 avril 2002. Version du document: 1.0 Les exemples utilisés et l'article lui-même sont libres d'utilisation, de publication et de redistribution sans accord préalable nécessaire de l'auteur. |
|
|
|
![]() ![]() |
Similar Topics
|
Lo-Fi Version | Time is now: 25th July 2008 - 08:35 PM |