La présentation est en train de télécharger. S'il vous plaît, attendez

La présentation est en train de télécharger. S'il vous plaît, attendez

Programme de baccalauréat en informatique Programmation Orientée Objets IFT-19946 Thierry EUDE Module 6. Gestion des erreurs et des exceptions : Fonctionnement.

Présentations similaires


Présentation au sujet: "Programme de baccalauréat en informatique Programmation Orientée Objets IFT-19946 Thierry EUDE Module 6. Gestion des erreurs et des exceptions : Fonctionnement."— Transcription de la présentation:

1 Programme de baccalauréat en informatique Programmation Orientée Objets IFT-19946 Thierry EUDE Module 6. Gestion des erreurs et des exceptions : Fonctionnement et utilisation Département dinformatique et de génie logiciel

2 2 Département dinformatique et de génie logiciel Erreurs et exceptions On rencontre fréquemment des erreurs ou des exceptions dans les programmes. Erreurs : des erreurs d'entrée de données par l'usager des erreurs du matériel ou de périphérique des erreurs de limitations ressources du système des erreurs de programmation de composants logiciels.

3 3 Département dinformatique et de génie logiciel Exceptions : débordement de capacité d'un nombre ; division par zéro ; paramètre de fonction invalide ; connexion réseau non disponible ou interrompue.

4 4 Département dinformatique et de génie logiciel Erreur d'entrée de données de l'utilisateur L'utilisateur peut : saisir une date invalide demander de lire un fichier inexistant demander d'afficher le contenu de i e dossier qui est en dehors des limites d'un conteneur. Dans un programme interactif : -on informe l'utilisateur du problème -on attend de nouvelles directives. Dans un programme non interactif : -on fait le rapport de l'erreur dans un fichier -on tente de continuer ou on arrête. Erreurs

5 5 Département dinformatique et de génie logiciel Erreur du matériel ou de périphérique Exemples : -le port série n'est pas disponible -l'imprimante peut être hors tension ou ne plus avoir de papier. Arrêt ou suspension de la tâche en attendant que le problème soit réglé. L'imprimante n'a plus de papier au milieu de la tâche. Le programme peut alors : avertir l'utilisateur de la situation attendre qu'il nous dise quoi faire sans quitter.

6 6 Département dinformatique et de génie logiciel Erreur de limitation de ressources du système Cas typiques : disque dur ou disquette plein plus de mémoire disponible plus de ressource Windows disponible (Font, Brush...) Si un scénario est détecté, on peut : avertir l'utilisateur de la situation en lui demandant de libérer des ressources (si possible) attendre ses instructions (réessayer ou annuler) sans quitter le programme.

7 7 Département dinformatique et de génie logiciel Erreur de programmation d'un composant logiciel Exemples typiques : tenter de créer une date invalide tenter d'obtenir le dessus d'une pile vide tenter d'obtenir un élément dans un vecteur qui est hors limite. difficile d'adopter une stratégie adaptée à toutes les situations : parfois, lancer une exception de contrat et arrêter le programme suffit. parfois, avertir l'usager, sauvegarder son travail et quitter élégamment est préférable.

8 8 Département dinformatique et de génie logiciel Réagir à ces conditions d'erreur au niveau du code retourner un code d'erreur assigner une valeur à une variable globale d'erreur ignorer l'erreur (!) imprimer un message d'erreur arrêter le programme lancer une exception.

9 9 Département dinformatique et de génie logiciel Retourner un code d'erreur Façon de faire très fréquemment rencontrée dans les programmes : une valeur ou un ensemble de valeurs indiquent une situation d'erreur. Exemple : la fonction fopen de la librairie du C standard retourne un pointeur valide si l'ouverture du fichier a été réussie un pointeur NULL autrement. FILE* fopen(const char* fichierP);

10 10 Département dinformatique et de génie logiciel Le programmeur a la responsabilité de vérifier le code de retour de la fonction pour s'assurer du succès de l'appel : FILE* fP = fopen("toto.txt"); if (fP != NULL) { // --- Écrire dans le fichier } else { // --- Gérer l'erreur }

11 11 Département dinformatique et de génie logiciel Dans certains cas, il est difficile de trouver une valeur désignant la situation d'erreur : Une fonction qui retourne un entier dont toutes les valeurs peuvent être valides n'a pas vraiment de moyen pour retourner une erreur (0 pouvant être valide). Souvent, on rencontre des standards dans lequel toutes les fonctions retournent un code d'erreur. Les valeurs de retour (données en retour) sont passées en paramètre.

12 12 Département dinformatique et de génie logiciel Exemple bool fonct1(double v, int& ret); int fonct2(double v, int& ret); fonct1 retourne true en cas de succès et false autrement. fonct2 pourrait retourner différentes valeurs entières spécifiant des cas d'erreur et un cas valide. Dans les deux cas, les valeurs retournées passent par les paramètres et le retour ne sert qu'aux codes d'erreur.

13 13 Département dinformatique et de génie logiciel Variable globale d'erreur La plupart des fonctions de la librairie standard du C fonctionnent avec la célèbre variable globale errno. Exemple : si on appelle unlink pour effacer un fichier, la fonction retourne 0 en cas de succès et -1 autrement. En cas d'erreur, on a assigné un code d'erreur à la variable globale errno : EACCES: Accès interdit ENOENT: Chemin d'accès ou fichier introuvable

14 14 Département dinformatique et de génie logiciel Exemple void main() { const char* fichierP = "log.bak"; if (unlink(fichierP) == -1) { if (errno==EACCES) { cout << "L'accès au fichier : " << fichierP << " est interdit" << endl; } else if (errno == ENOENT) { cout << "Le fichier ou le chemin d'acces" << " est introuvable" << endl; }

15 15 Département dinformatique et de génie logiciel Problème important : approche non compatible avec une architecture multi- tâche. On doit protéger l'accès à cette variable globale... On peut perdre de l'information si deux erreurs se produisent coup sur coup. La première erreur est écrasée par la seconde potentiellement on peut mal interpréter la signification de l'erreur.

16 16 Département dinformatique et de génie logiciel Ignorer l'erreur Prendre la décision de ne rien faire en cas de demande erronée peut parfois être la seule solution «raisonnable». Beaucoup de fonctions de la librairie standard ont un comportement «non défini» lors d'appel invalide. Que ce passe-t-il si on tente d'accéder un vecteur en dehors de ses limites ? (On ne sait pas !!!) Ce style de programmation n'est pas à favoriser car il peut masquer des erreurs importantes.

17 17 Département dinformatique et de génie logiciel Imprimer un message d'erreur Imprimer un message d'erreur décrivant l'erreur : est acceptable pour un petit programme en phase de débogage. est inacceptable pour un logiciel commercial. L'utilisateur ne devrait voir que des messages qui ont du sens pour lui et sur lesquels il peut prendre action. Exemple : si on l'avertit que le disque est plein, il peut effacer des fichiers pour libérer de l'espace et poursuivre.

18 18 Département dinformatique et de génie logiciel Arrêter le programme En phase de développement, il est tout à fait acceptable d'arrêter le programme ou d'offrir de démarrer le débuggeur à l'endroit de l'erreur. Pour un produit commercial, ce n'est pas acceptable. L'usager peut avoir travaillé plusieurs minutes (heures) avant de perdre son travail (...) Au minimum, il faut enregistrer les documents modifiés sur disque et enlever les fichiers temporaires.

19 19 Département dinformatique et de génie logiciel Lancer une exception Les exceptions ont été ajoutées dans beaucoup de langages OO dont le C++. Le mécanisme des exceptions est un moyen sûr et pratique : pour lancer des exceptions sur le site de l'erreur. transférer le contrôle à une autre partie du code qui pourra gérer la situation avec compétence. Exemple : «Incapable d'écrire ces bytes» pourrait être devenir «Disque plein» à un niveau supérieur.

20 20 Département dinformatique et de génie logiciel Synthèse Erreurs Réactions aux erreurs

21 21 Département dinformatique et de génie logiciel Exceptions Lancer une exception Lorsque se produit une erreur qui ne peut être prise en charge à l'endroit de sa détection, une exception peut être lancée avec la commande throw : throw e; où e peut être n'importe quoi : un entier, une string, ou beaucoup mieux, un objet. throw "Division par zéro"; throw ERR_DIVISION_ZERO; throw DivParZeroException();

22 22 Département dinformatique et de génie logiciel Lancer une exception Il est préférable d'utiliser les objets pour représenter les exceptions : utile pour spécifier le type de l'exception auquel on fait face ; permet de définir des sites d'interception basés sur le type d'exception ; permet de transporter de l'information dans l'objet du site de l'erreur jusqu'au site d'interception de l'exception.

23 23 Département dinformatique et de génie logiciel Une fonction ne retourne pas normalement Lorsqu'une fonction lance une exception, le mécanisme veut que le système se mette immédiatement à la recherche d'un site d'interception pour cette exception. La fonction ne retourne pas normalement, l'exécution de la fonction se termine immédiatement l'exécution est transférée au site d'interception le plus proche (pour cette exception). // --- lance DivParZeroException double r = divise (3, 0); // --- Ne sera pas exécuté cout << "Résultat: " << r << endl;

24 24 Département dinformatique et de génie logiciel Gérer une exception Les sites d'interception des exceptions sont spécifiés à l'aide de blocs try-catch. try { // code pouvant lancer une exception } catch (Type-exception e) { // e contient de l'information sur // l'exception. // code de gestion de l'exception }

25 25 Département dinformatique et de génie logiciel double divise (int d, int n) { if (n==0) throw DivParZeroException(); return (double)d/n; } try { // --- lance DivParZeroException double r = divise (3, 0); cout << "Résultat: " << r << endl; } catch (DivParZeroException& e) { // --- Traitement de l'exception }

26 26 Département dinformatique et de génie logiciel Le mécanisme peut sembler un peu lourd si on veut l'utiliser pour vérifier chaque appel de fonction comme : try { double n = pile.pop(); } catch (ContratException& e) {... }

27 27 Département dinformatique et de génie logiciel Gérer une exception : résumé Les exceptions sont utiles pour gérer des erreurs pouvant se produire n'importe où dans un sous-système. Le transfert de contrôle du point de détection de l'erreur à un point de gestion compétent permet de mieux gérer les erreurs. Ne pas être capable d'écrire un entier dans une stream (point de détection de l'erreur) devient détection d'une disquette pleine (sur le site de gestion de l'exception). à ce niveau d'intervention, on peut interagir avec l'utilisateur dans des termes compréhensibles pour lui.

28 28 Département dinformatique et de génie logiciel Hiérarchie d'exceptions La gestion des exceptions est basée sur le type d'exception (la classe), construire de petites classes appartenant à une hiérarchie. La librairie standard du C++ a déjà mis en place un certain nombre d'exceptions. La théorie du contrat définit des exceptions qui sont attachées à cette hiérarchie Du côté logic_error, i.e. erreur de programmation. Du côté runtime_error par contre, il s'agit d'exception pouvant toujours se produire.

29 29 Département dinformatique et de génie logiciel Classes définies dans la librairie standard

30 30 Département dinformatique et de génie logiciel Gérer plus d'une exception À partir d'un bloc try-catch, on peut gérer plusieurs exceptions à la fois : try { // Code pouvant lancer des exceptions } catch (overflow_error& o) { // Gère des exceptions d'overflow } catch (underflow_error& u) { // Gère des exceptions d'underflow }

31 31 Département dinformatique et de génie logiciel Si le code dans le bloc try génère une exception de type overflow_error ou underflow_error, le traitement correspondant est activé. Si une exception d'un type différent est lancée, elle doit être gérée ailleurs sur un site d'interception du bon type. Si un tel site n'existe pas, le programme s'arrêtera en donnant une erreur du type "Unhandle exception".

32 32 Département dinformatique et de génie logiciel Classes d'exception de contrat std::logic_error ContratException m_ligne : int m_fichier : string m_expression : string reqTexteException() : string InvariantExceptionAssertionExceptionPostconditionExceptionPreconditionException

33 33 Département dinformatique et de génie logiciel Hiérarchie d'exceptions de contrat Si on veut gérer toutes les exceptions de contrat, mentionner catch (ContratException& e) toutes les exceptions de contrat : precondition, postcondition, invariant et assertion seront attrapées. Si on veut gérer seulement les préconditions, mentionner : catch (PreconditionException &e). On pourrait gérer toutes les erreurs de programmation en mentionnant : catch (logic_error& e)

34 34 Département dinformatique et de génie logiciel Attraper toutes les exceptions et relancer À l'occasion, nous voulons attraper toutes les exceptions (sans exception!!) qui passent à un endroit donné : pour faire une action protectrice pour faire un nettoyage quelconque. try { // code } catch (...) { // Gestion de n'importe quelle exception throw; // Relance l'exception }

35 35 Département dinformatique et de génie logiciel L'énoncé catch(...) avec les 3 petits points permet de gérer n'importe quel type d'exception. L'énoncé throw sans argument dans un bloc catch permet de relancer l'exception courante de nouveau. De fait, on doit toujours relancer une exception qu'on ne sait pas comment gérer (quoiqu'il aurait été préférable de ne pas l'avoir interceptée). Une exception non interceptée arrête le programme.

36 36 Département dinformatique et de génie logiciel La pile d'appel Gestion de la pile d'appel par le mécanisme des exceptions. Le flot linéaire d'exécution des instructions ne s'applique plus lorsque qu'une exception est lancée. Au moment où une exception se produit, le contrôle passe au site d'interception le plus proche pour cette exception. Tous les objets entre l'énoncé throw et l'énoncé catch seront détruits et leur destructeur est appelé. Normalement les objets sur la pile sont détruits lorsque l'exécution du programme atteint la fin d'un bloc ou d'une fonction.

37 37 Département dinformatique et de génie logiciel Le mécanisme des exceptions garantit que tous les destructeurs des objets sur la pile seront appelés. après avoir lancé une exception et l'avoir récupéré, on peut continuer l'exécution. Gérer les ressources de façon cohérente en fonction de cette nouvelle réalité. point du catch point du throw main() f1() f2() f3() f4()

38 38 Département dinformatique et de génie logiciel Gestion des ressources La possibilité qu'une exception puisse être lancée et qu'on ne puisse plus compter sur le flot linéaire d'exécution ajoute une préoccupation : Sommes-nous «exception-safe» ? Exemples: FILE* fichierP = fopen("input.dat"); foo(fichierP); // peut lancer une exception fclose(fichierP); // peut ne jamais être exécuté Employe* eP = new Employe(); foo(eP); // peut lancer une exception delete eP; // peut ne jamais être libérée

39 39 Département dinformatique et de génie logiciel FILE* fP = fopen ("input.dat"); try { foo (fP); } catch (...) { fclose (fP); throw; } fclose (fP); Employe* eP = new Employe(); try { foo (eP); } catch (...) { delete eP; throw; } delete eP; Attraper toutes les exceptions, fermer le fichier ou libérer la mémoire et relancer l'exception est techniquement correct. Appliqué à grande échelle, la vie du programmeur deviendrait pire qu'avant...

40 40 Département dinformatique et de génie logiciel Structurer le code pour bénéficier de la gestion automatique des ressources en utilisant les constructeurs et les destructeurs des classes. En utilisant une variable locale de type ifstream, on ouvre le fichier par le constructeur et le fichier est fermé par le destructeur : ifstream fs("input.dat"); foo (fs); Le fichier sera fermé lorsque le programme sera à la recherche d'un site d'interception pour une exception et que tous objets seront désalloués.

41 41 Département dinformatique et de génie logiciel Même problème avec la mémoire allouée sur le monceau. On ne doit pas conserver de pointeur comme variable d'une fonction. La classe auto_ptr<> du standard permet de conserver les pointeurs dans des classes dont le destructeur gère la désallocation. #include #include "Employe.h" using namespace std; - Pointeur sur la pile dans une fonction Employe* eP = new Employe("Yves"); - Pointeur comme attribut d'un objet auto_ptr pstr(new Employe("Yves"));

42 42 Département dinformatique et de génie logiciel Quelles exceptions lancer ? Une exception non gérée résulte en un programme arrêté, il est vital que le code minimise le nombre d'exceptions lancées et que celles-ci soient clairement documentées. Ne jamais se servir des exceptions pour retourner des résultats de calcul. on peut ne pas tenir compte du type de retour d'une méthode sans péril. ce n'est pas le cas avec une exception --> arrêt immédiat du programme.

43 43 Département dinformatique et de génie logiciel Synthèse Exception Lancer: Attraper: Simple: Multiple: Tous: Objets:


Télécharger ppt "Programme de baccalauréat en informatique Programmation Orientée Objets IFT-19946 Thierry EUDE Module 6. Gestion des erreurs et des exceptions : Fonctionnement."

Présentations similaires


Annonces Google