1 La gestion des exceptions C++ Un programme peut rencontrer des conditions exceptionnelles qui risquent de compromettre la poursuite de son exécution.

Slides:



Advertisements
Présentations similaires
Réaliser en Java un programme client d’une Base de Données
Advertisements

Cours de C – Séance dexercices 12 Octobre Exercice 5 Idem quexercice 1 : lire une ligne au clavier Sans limitation de la longueur de la ligne (utilisez.
Patrick Reuter maître de conférences
gestion des exceptions
GEF 243B Programmation informatique appliquée
GEF 243B Programmation informatique appliquée
POO.
M. BENJELLOUN : Info II Mohammed BENJELLOUN Service dInformatique Faculté Polytechnique de Mons
Traitement des erreurs en Java
Principes de programmation (suite)
Tests Programmation par contrats
POO-L3 H. Fauconnier1 Chapitre IV 1. classe Object, clonage 2. interfaces 3. classes internes et imbriquées.
Structures de contrôle de l’exécution
Les algorithmes: complexité et notation asymptotique
Les pointeurs 1. Notion de pointeurs cest Travailler avec les pointeurs cest Se rapprocher du matériel Nécessite de bien connaitre le fonctionnement de.
Les exceptions. Quest ce quune exception ? Une erreur dans le programme Due à un bug ou un cas « anormal » Gestion complète en java : JVM Dans dautre.
IFT1025, Programmation 2 Jian-Yun Nie
Base de programmation Script unity en c#.
Bases de la programmation en C++ 1 Les enchaînementsdinstruction Séquentiels. Exécutions dinstructions les unes à la suite des autres. Instructions séparées.
Techniques de test Boulanger Jean-Louis.
Algorithmique et Programmation
Test et débogage Tests unitaires. Gestion d’erreurs. Notion d’état, de pré-condition et de post-condition. Assertion. Traces de programme. Débogueur et.
Structures de données IFT Abder Alikacem Gestion des exceptions Département dinformatique et de génie logiciel Édition Septembre 2009.
Révision des notions OO et Java Semaine 1 Jian-Yun Nie.
Contrôle de types Les types en programmation Expressions de types Un contrôleur de types Equivalence de types Conversions de types Généricité.
Architecture et technologie des ordinateurs II
IFT 6800 Atelier en Technologies d’information
1 La récursion. Nous avons vu qu'un programme est constitué d'un ensemble de fonctions. Il est possible pour une fonction donnée d'appeler une autre fonction.
Chapitre 9 Les sous-programmes.
COURS DE PROGRAMMATION ORIENTEE OBJET :
Méthode et Outils pour la Programmation
Christine Bonnet SOURCES : « Samples » dOracle, « Oracle 8 » R. Chapuis PRO*C – C ++
Programme de baccalauréat en informatique Programmation Orientée Objets IFT Thierry EUDE Module 6. Gestion des erreurs et des exceptions : Fonctionnement.
99 Réutilisation du code grâce à l'héritage. 9-2 Objectifs À la fin de ce cours, vous serez capables de : Définir l'héritage Utiliser l'héritage pour.
Structures de données IFT-2000 Abder Alikacem La récursivité Semaine 5 Département dinformatique et de génie logiciel Édition Septembre 2009.
Répéter dans un programme avec une Instruction itérative
Récursion IFT1025: Programmation 2 Jian-Yun Nie. Définition Le fait pour un programme ou une méthode de s'appeler lui-même. Par exemple –Définir la notion.
INF1101 Algorithmes et structures de données
Une introduction à Java
Structures alternative et répétitive
Introduction Un test sur les tests Ce que n’est pas le test
Formation C++. Hello World ! #include /* Commentaire sur plusieurs lignes */ int main() { //Affiche hello world std::cout
1111 Gestion des exceptions Objectifs À la fin de ce cours, vous serez capables de : • Expliquer les concepts de base de la gestion des exceptions.
Programmation Orienté Objet en C++ Ricard julien.
La librairie assert.h.
Structures de données IFT Abder Alikacem Semaine 2 Tests sur les pointeurs Département d’informatique et de génie logiciel Édition Janvier 2009.
Animateur : Med HAIJOUBI
2.1 - Historique Chapitre 2 : Introduction au langage C++
Raffinement de modèles JML Julien Groslambert LIFC Besançon Réunion GECCOO - 25 Octobre 2005 FRE 2661.
SPIP SPIP est le système de publication développé par le minirézo.
Programmation en Java Tableaux NGUYEN Thi Minh Tuyen
GESTION ET TRAITEMENT DES ERREURS
Types Abstraits.
Notions avancées du C++
Master 1 SIGLIS Java Lecteur Stéphane Tallard Chapitre 6 – Exceptions.
Les tests.
12/04/ Les exceptions Cours 11 Cours 11.
1 Programmation en C++ Marianne Morris. 2 Intro générale à la programmation On a déjà étudié le langage assembleur Langage de bas niveau Meilleur que.
Exception Handling "Unfortunately, it's almost accepted practice to ignore error conditions, as if we're in a state of denial about errors." Bruce Eckel.
6ième Classe (Mercredi, 17 novembre) CSI2572
Conception de Programmes - IUT de Paris - 1ère année Cours 2 – Références et passage de paramètres Les Références –Introduction aux références.
Chapitre VII Techniques plus avancées à travers le concept de classe.
Les structures de contrôle
1 Complément JAVA les assertions. 2 lan Tests et erreurs Assertions en Java Utilisation Bonne pratique des assertions.
Langage de programmation
PRO-1027 Programmation Scientifique en C
Exception Handling "Unfortunately, it's almost accepted practice to ignore error conditions, as if we're in a state of denial about errors." Bruce Eckel.
Accompagnement et suivi de tous les élèves
Int 10. Int 6.
Transcription de la présentation:

1 La gestion des exceptions C++ Un programme peut rencontrer des conditions exceptionnelles qui risquent de compromettre la poursuite de son exécution La détection dun incident et son traitement dans les programmes importants doivent se faire dans des parties différentes du code. Exemple trivial : int *pint; pint = new int; If (pint == NULL) { cout << Manque de mémoire pour pint << endl; exit(1); }

2 La gestion des exceptions C++ La solution moderne du problème : les exceptions. Elles permettent le découplage total de la détection dune anomalie (exception) de son traitement en saffranchissant de la hiérarchie des appels. Une exception est une rupture de séquence déclenchée par une instruction throw comportant une expression (objet) dun type (classe) donné.

3 Gestion de lexception (1) La gestion de lexception se fait en deux étapes : Une erreur détectée va lever une exception (throw) Un gestionnaire va récupérer cette exception et la traiter convenablement (catch) Pour pouvoir détecter les exceptions, les instructions susceptibles de lever des exceptions sont incluses dans un bloc spécifique (try)

4 Gestion de lexception (2) Définition de lexception class exception_triviale { … }; Utilisation et levée de lexception … try { int i = 0; i--; if (i NMAX) { exception_triviale e; throw(e); } … } Interception et traitement de lexception catch (exception_triviale e) { … }

5 Utilisation dun gestionnaire dexception #include typedef int Erreur; class vecteur { protected: int *pespace; int taille; public: vecteur (int _taille){taille=_taille;pespace=new int[taille];} //surcharge d'opérateur d'adressage avec une fonction - membre int & operator[](int i); }; int& vecteur::operator[](int i){ if((i =taille)) throw -1; return pespace[i]; } int main(){ try{ vecteur v(2); v[2]=1; } catch(Erreur){ cerr<<"Indice invalide"<<endl; } return 0; } Resultat : Indice invalide Commentaires : cest une exception avec le passage dun type catch(Erreur), Erreur étant un type Catch peut être interprété comme le nom de la fonction – gestionnaire En fait le bloc catch contient la séquence de traitement correspondante

6 Gestionnaire avec passage dune valeur #include enum Erreurs {depasseG, depasseD}; class vecteur { protected: int *pespace; int taille; public: vecteur (int _taille){taille=_taille;pespace=new int[taille];} //surcharge d'opérateur d'adressage avec une fonction - membre int & operator[](int i); }; int& vecteur::operator[](int i){ if(i<0) throw depasseG; if(i>=taille) throw depasseD; return pespace[i]; } int main(){ try{ vecteur v(2); v[2]=1; } catch(Erreurs e){ if(e==depasseG) cout<<"Indice trop petit"<<endl; if(e==depasseD)cout<<"Indice trop grand"<<endl; } return 0; } Resultat : Indice trop grand Commentaire : gestionnaire avec une valeur permet de gérér les exceptions plus finement

7 Gestion avec un objet-exception class vecteur { protected: int *pespace; int taille; public: class Exception_portee{ public : int indice; Exception_portee(int i){indice=i;} }; vecteur(int_taille){taille=_taille; pespace=new int[taille];} int & operator[](int i); }; int& vecteur::operator[](int i){ if((i =taille)) throw Exception_portee(i); return pespace[i]; } int main(){ try{ vecteur v(2); v[2]=1; } catch(vecteur::Exception_portee e){ cerr<<"Erreur de depassement dans le tableau i= "<<e.indice<<endl; } return 0; } Resultat : Erreur de depassement dans le tableau i= 2 Commentaire : gestionnaire avec une valeur permet de gérér les exceptions plus finement

8 Flot dexécution (UML) Vecteur v Exception_portee e Diagramme de séquence

9 Commentaires Le modèle de gestion des exceptions proposé par C++ ne permet pas de reprendre lexécution à partir de linstruction ayant levé lexception, mais le permet après le bloc catch correspondant Si le bloc try/catch nest pas prévu, lexception déclenchée par throw provoque larrêt de lexécution dans la fonction ou méthode courante.

10 Exemple avec exit #include enum Erreurs {depasseG, depasseD}; class vecteur { protected: int *pespace; int taille; public: vecteur (int _taille){taille=_taille;pespace=new int[taille];} //surcharge d'opérateur d'adressage avec une fonction - membre int & operator[](int i); }; int& vecteur::operator[](int i){ if(i<0) throw depasseG; if(i>=taille) throw depasseD; return pespace[i]; } int main(){ try{ vecteur v(2); v[2]=1; } catch(Erreurs e){ if(e==depasseG) cout<<"Indice trop petit"<<endl; if(e==depasseD)cout<<"Indice trop grand"<<endl; exit(-1); } return 0; } Commentaire : larrêt définitif du programme lors du traitement de lexception

11 Exemple de plusieurs exceptions #include class vecteur { protected: int *pespace; int taille; public: class Exception_creation{ public : int hors_indice; Exception_creation(int i){ hors_indice=i; } }; class Exception_limite{ public : int indice; Exception_limite(int i){ indice=i;} }; vecteur (int _taille){if(_taille<=0) throw Exception_creation(_taille); taille=_taille; pespace=new int[taille];} int & operator[](int i); };// fin de la déclaration de la classe int& vecteur::operator[](int i){ if((i =taille)){ Exception_limite e(i); throw e; } return pespace[i]; }

12 Exemple de plusieurs exceptions int main(){ try{ vecteur v(-2); v[2]=1; } catch(vecteur::Exception_creati on e){ cerr<<"Erreur de depassement a la creation i= "<<e.hors_indice<<endl; } catch (vecteur::Exception_limite e){ cerr<<"Erreur de depassement dans le tableau i= "<<e.indice<<endl; exit(1); } return 0; } Quelle exception est active? Résultat? Erreur de dépassement à la création i = 2 Commentaires : les exceptions peuvent être déclanchées par nimporte quelle fonction car les définitions des classes sont connues.

13 Poursuite dexécution du programme Il est impossible de reprendre lexécution du programme à linstruction suivant le déclenchement de lexception mais Le flot de contrôle peut être repris après le bloccatch Souvent le bloc try couvre toute une fonction de sorte quaprès lexécution dun gestionnaire dexception ne provoquant pas darrêt, il y a retour de la fonction

14 Retour du flot de contrôle Exemple int main(){ try{ vecteur v(-2); v[2]=1; } catch(vecteur::Exception_creation e){ cerr << "Erreur de dépassement à la création i="<< e.indice << endl; } catch (vecteur::Exception_limite e){ cerr << "Erreur de dépassement dans le tableau i= << e.indice << endl; } cout << Reprise après les exceptions" << endl; return 0; } Résultats : Erreur de dépassement à la création i=-2 Reprise après les exceptions

15 Choix du gestionnaire Le gestionnaire reçoit toujours une copie de lexpression passée à throw même sil sagit de la transmission par référence. Exemple : Exception_limite c; throw c; // une copie dobjet c est crée. Lorsquune exception est transmise à un bloc try, on recherche, dans les différents blocs catch associés, un gestionnaire approprié au type de lexpression mentionnée dans linstruction throw. Le mécanisme est le même que pour la recherche des fonctions-membres dans la hiérarchie des classes

16 Prise en compte des sorties des blocs Exemple : void f(int n) { vecteur v1(5); try{ vecteur v2(5); v1[n]=1; //on ne sait pas si on est bien dans les limites } catch (vecteur::Exception_limite e){ cerr << "Err de dépass dans le tableau i= << e.indice << endl; } cout << "Je reprends après les exceptions" << endl; // ici v1 est connu, v2 a été détruit } Le méchanisme de gestion des exceptions appelle le destructeur de tout objet automatique déjà construit et devenant hors de portée

17 Choix du gestionnaire Hiérarchie des classes dexceptions class Exception_vecteur {…}; class Exception_creation : public Exception_vecteur {}; class Exception_limite : public Exception_vecteur{}; // ces classes sont déclarées à lextérieur de la classe vecteur; void f() {… throw Exception_creation; throw Exception_limite; } int main () { try { … f(); … } catch (Exception_vecteur e) { cout<< Interception des deux ici car enfants de la classe Exception_vecteur << endl; }

18 Le cheminement des exceptions Quand une exception est levée par une fonction, on cherche tout dabord un gestionnaire dans léventuel bloc try/catch associé à cette fonction Si lon nen trouve pas, on poursuit la recherche dans un éventuel bloc try/catch associé à une fonction appelante Si aucun gestionnaire dexception nest trouvé on appelle la fonction terminate. Par défaut terminate appelle la fonction abort.

19 Version 1 int main() { try{ f1(); // dépassement de limite! } catch (vecteur::Exception_limite e) { cerr<<"Dans main : Erreur de dépassement dans le tableau i="<<e.indice<<endl; } cout << Reprise après les exceptions" << endl; return 0; } void f1() { try { vecteur v(10); v[10]=0; // Attention ! vecteur v1(-1); } catch (vecteur::Exception_creation e) {// est déclenchée par le constructeur cout<<"Dans f1 : Exception_creation i= "<<e.hors_indice<<endl; } } Résultat : Dans main : Erreur de dépassement dans le tableau i=10 Reprise après les exceptions

20 Version 2 int main() { try { f1(); } catch (vecteur::Exception_limite e) { cerr<<"Dans main : Erreur de dépassement dans le tableau i= "<<e.indice<<endl; } cout << Reprise après les exceptions" << endl; return 0; } void f1() { try{ vecteur v(10); v[9]=0; vecteur v1(-1); } catch (vecteur::Exception_creation e){ cout<<"Dans f1 : Exception_creation i= "<<e.hors_indice<<endl; } } Résultat : Dans f1 : Exception_creation i= -1 Reprise après les exceptions

21 Redéclenchement des excéptions (I) Dans un gestionnaire, linstruction throw (sans expression) retransmet lexception au niveau englobant. catch(..){ … throw; } Cette possibilité permet de compléter le traitement standard dune exception par un traitement complémentaire spécifique

22 Redéclenchement des exceptions (II) #include using namespace std; void f(); void main(void) { try { f(n); } catch (int) { cout << « Exception int dans main" << endl; exit(-1); } cout << "suite bloc try du main" << endl; } void f(){ try { int n; throw n; } catch (int) { cout << « Exception int dans f" << endl; throw; } }//fin void f() Résultat : Exception int dans f Exception int dans main

23 Les exceptions standard C++ Les exceptions standard sont des classes dérivées dune classe de base exception Leur déclaration figure dans le fichier-entête stdexcept Certaines peuvent être déclenchées par des fonctions ou des opérateurs de la bibliothèque standard Example : bad_alloc : échec dallocation mémoire par new

24 Spécification dinterface(I) Une fonction peut spécifier les exceptions quelle est susceptible de déclencher. Elle le fait à laide de throw placé juste après lidentificateur de la fonction void f() throw (A,B){ …} // f est censée ne déclencher que les exceptions A et B Toute exception non prévue et déclenchée à lintérieur de la fonction (ou dune fonction appelée) entraîne lappel de la fonction «unexpected » « unexpected » => terminate =>abort par défaut.

25 Spécification dinterface (II) #include using namespace std; void f(int) throw(int); void main(void) { int n; cout << "Entier (0 a 2) : " ; cin >> n; try { f(n); } catch (int) { cout << "exception int dans main" << endl; } cout << "suite bloc try du main" << endl; } void f(int n) throw(int) { try { cout << "n = " << n << endl; switch (n) { case 0 : { double d = 0; throw d;//traité par f break; } case 1 : { int n = 0; throw n; //traité par main break; } case 2 : { float f = 0; throw f;//appel unexpected break; } catch (double) { cout << "exception double dans f" << endl; } cout << "suite du bloc try dans f et retour appelant" << endl; }

26 Spécification dinterface(III) void f(int n) throw(int) { try { cout << "n = " << n << endl; switch (n) { case 0 : { double d = 0; throw d;//traité par f break; } case 1 : { int n = 0; throw n; //traité par main break; } case 2 : { float f = 0; throw f;//appel unexpected break; } catch (double) { cout << "exception double dans f" << endl; } cout << "suite du bloc try dans f et retour appelant" << endl; } Résultats : Entier (0 à 2) : 0 n=0 exception double dans f Entier (0 à 2) : 1 n=1 exception int dans main Entier (0 à 2) : 2 n=2 Fin anormal ( exception std bad_exception)

27 Les exceptions standard C++ La bibliothèque stadard (stdl) comporte quelques classes qui dérivent dun classe de base exception Logic_error Domain_error Invalid_argument Length_error Out_of_range Runtime_error range_error overflow_error Underflow_error Bad_alloc //échec dallocation mémoire par new Bad_cast //échec de lopérateur dynamic_cast Bad_exception //erreur de spécification dexception (peut être déclenché par unexpected) Bad_typeid //echec de la fonction typeid

28 Les exceptions standard C++(2) #include using namespace std; int tableau[10] = { 10, 20, 30, 40, 50, 60, 70, 80, 90, 100 }; int f(int i); void main(void) { try { int n; cout > n; int i = f(n); cout << "i = " << i << endl; } catch (exception& e) { cout << "Exception : " << e.what() << endl; } int f(int i) { if (i >= 0 && i < (sizeof(tableau) / sizeof(int))) { return tableau[i]; } throw out_of_range("index hors domaine"); } Résultats : Entier : -1 Exception : index hors domaine Entier : 0 i= 10

29 Création des exceptions dérivées de la classe Exception Raisons (1) Faciliter le traitement des exceptions : interception de toute exception avec le simple gestionnaire : catch (exception & e){…} Cela est vérifié pour les exceptions dérivées de la classe exception. (2) Utiliser la fonction what de la classe exception, qui renvoie la chaîne de caractères utilisée par le constructeur de lexception

30 Exemple de la fonction what #include using namespace std; int main(){ try{ throw range_error("anomalie_1"); } catch (range_error &re){ cout << "exception: << re.what() << endl; } return 0; } Résultats : exception: anomalie_1

31 Un vrai exemple dutilisation de « range_error » #include using namespace std; int main(){ try{ int i=100; double epsilon=0.1; double somme=0.0; for(int k=1; k<=100;k=k+10) { epsilon=epsilon/k; if (epsilon<=0.001) throw range_error("anomalie_1"); else {somme=somme+1/epsilon; cout<<"somme courante"<<somme<<endl;} } cout<<"somme = "<<somme<<endl; } catch (range_error &re){ cout<<"exception: "<<re.what()<<endl; } somme courante10 somme courante120 exception: anomalie_1 Press any key to continue Résultat dexecution

32 Utilisation de lexception Bad_Alloc #include "stdafx.h" #include #define MAX_NUMBER using namespace std; int _tmain(int argc, _TCHAR* argv[]) { try { int* ptrTab; for (int i=0;i<MAX_NUMBER; i++) ptrTab=new int[MAX_NUMBER]; } catch (bad_alloc & b) { cout<<"Exception d'allocation de mémoire par new"<<endl; cout<<"Vous êtes trop gourmand!" <<endl<<b.what()<<endl; } return 0; } Exception d'allocation de mémoire par new Vous êtes trop gourmand! bad allocation Press any key to continue lexception « bad-alloc » est déclenchée par la fonction « new » de la librairie standard.

33 Héritage de la classe exception #include using namespace std; class monException1 : public exception { public: monException1() {} // Surcharge de la méthode virtuelle what virtual const char* what() const { return "Mon exception no 1"; } }; class monException2 : public exception { public: monException2(char* texte) { this- >texte = texte; } // Surcharge de la méthode virtuelle what virtual const char* what() const { return texte; } private: char* texte; }; void main(void) { try { cout << "Bloc try 1" << endl; throw monException1(); } catch (exception& e) { cout << "Exception : " << e.what() << endl; } try { cout << "Bloc try 2" << endl; throw monException2("deuxieme type"); } catch (exception& e) { cout << "Exception : " << e.what() << endl; }