37
Structures de données IFT-10541 Abder Alikacem Abder Alikacem Gestion des exceptions Département d’informatique et de génie logiciel Édition Septembre 2009

Structures de données IFT-10541 Abder Alikacem Gestion des exceptions Département dinformatique et de génie logiciel Édition Septembre 2009

Embed Size (px)

Citation preview

Page 1: Structures de données IFT-10541 Abder Alikacem Gestion des exceptions Département dinformatique et de génie logiciel Édition Septembre 2009

Structures de donnéesIFT-10541

Abder AlikacemAbder Alikacem

Gestion des exceptions

Département d’informatique et de génie logiciel

Édition Septembre 2009

Page 2: Structures de données IFT-10541 Abder Alikacem Gestion des exceptions Département dinformatique et de génie logiciel Édition Septembre 2009

• Erreur, exception …• Solution objet• Coder des exceptions en C++• Exceptions standard du langage

Plan

Page 3: Structures de données IFT-10541 Abder Alikacem Gestion des exceptions Département dinformatique et de génie logiciel Édition Septembre 2009

Contexte

Exemples de dysfonctionnements (ou anomalies) :• demander la valeur du sommet d ’une pile vide• Empiler dans une pile pleine

Etat des données peuvent rendre compte du dysfonctionnement exception contrôlée

Exemples d ’erreurs (à l ’exécution) • limite atteinte de la capacité mémoire• delete sur un pointeur non défini

=> arrêt brutal de l ’exécution du programme

Page 4: Structures de données IFT-10541 Abder Alikacem Gestion des exceptions Département dinformatique et de génie logiciel Édition Septembre 2009

BUT

On cherche à gérer les exceptions afin de • Nettoyer les données,• Rétablir l’application dans son fonctionnement normal,• Terminer l’application.

Une exception est l ’interruption gérée de l ’application à la suite d ’un dysfonctionnement. Le but de la gestion des exceptions est de réaliser des traitements spécifiques aux événements qui en sont la cause.

Page 5: Structures de données IFT-10541 Abder Alikacem Gestion des exceptions Département dinformatique et de génie logiciel Édition Septembre 2009

Solution traditionnelle

Les fonctions susceptibles de subir des dysfonctionnements renvoient une information précisant :

• ou bien que l’application s ’est déroulée normalement• ou bien qu’une anomalie X a été rencontrée

Exemple : les traitements de la classe pile peuvent générer des dysfonctionnements quand la pile est vide (ex : dépiler) ou quand la pile est pleine (ex : empiler)

Page 6: Structures de données IFT-10541 Abder Alikacem Gestion des exceptions Département dinformatique et de génie logiciel Édition Septembre 2009

Solution traditionnelle

# include <iostream.h>

enum exception {PilePleine, PileVide, Valider };

template <class X>class pile{ public :

pile(void); // constructeur~ pile(void); // Destructeurexception sommet (X&) ; // sélecteur : sommetbool vide(void); // Sélecteur : pile vide ?exception empiler (const X&); // empiler l ’élément donnéexception depiler(void); // dépiler l ’élément placé au sommet

private :...

};

// Classe Pile Générique// Traitement des exceptions par retour d'une valeur

Page 7: Structures de données IFT-10541 Abder Alikacem Gestion des exceptions Département dinformatique et de génie logiciel Édition Septembre 2009

Solution traditionnelle

Les fonctions susceptibles de subir des dysfonctionnements renvoient une information précisant :

• ou bien que l’application s ’est déroulée normalement• ou bien qu’une anomalie a été rencontrée

INCONVENIENTS • Nécessite un contrôle à chaque appel• Solution avec des switch, compliquée, difficile à maintenir.• Dans le code : mélange des traitements du fonctionnement normal et ceux gérant les exceptions.• L’erreur n ’est pas forcément à corriger dans la méthode appelante directe. • Les constructeurs et destructeurs n ’on pas de type retour.

Page 8: Structures de données IFT-10541 Abder Alikacem Gestion des exceptions Département dinformatique et de génie logiciel Édition Septembre 2009

Solution : lancer une exception

IDEE :Eviter d ’encombrer le code pour tester un comportement anormal=> séparer le code propre à l’application de celui qui gère des dysfonctionnements. La fonction dans laquelle survient un dysfonctionnement se contente de lancer une exception.

template <class X>

pile<X>& pile<X>:: operator+= (const X& e){ if (indexsommet+1 <maximum) {

indexsommet+=1; t[indexsommet]=e;

return (*this); }

elsethrow "débordement de pile";

}

Page 9: Structures de données IFT-10541 Abder Alikacem Gestion des exceptions Département dinformatique et de génie logiciel Édition Septembre 2009

Structure de contrôle throw/...try/catch

throw exp est une expression de type void

Elle déroute l ’exécution normale d ’une fonction. L ’exécution peut alors être transférée à un autre point de l ’application pour traiter l ’anomalie (bloc try catch).

L ’expression est de type quelconque sauf void. Elle est évaluée puis transmise aux fonctions en attente d ’exécution, de la dernière fonction appelée vers la première.

Si rien de particulier n ’a été programmé pour traiter le problème alors le contrôle est passé à une fonction prédéfinie terminate.

Par défaut, l ’action de cette fonction est d ’exécuter la fonction abort du langage C.

Page 10: Structures de données IFT-10541 Abder Alikacem Gestion des exceptions Département dinformatique et de génie logiciel Édition Septembre 2009

Structure de contrôle throw/...(try/catch)

template <class X>

pile<X>& pile<X>:: operator+= (const X& e){ if (indexsommet+1 <maximum) {

indexsommet+=1; t[indexsommet]=e;

return (*this); }

elsethrow "débordement de pile";

}

int main (void) { ...P+=(...)... }

terminate

Page 11: Structures de données IFT-10541 Abder Alikacem Gestion des exceptions Département dinformatique et de génie logiciel Édition Septembre 2009

Structure de contrôle throw/...try/catch

Un bloc peut être déclaré réceptif aux exceptions. Il est alors capable d ’attraper une exception.

Syntaxe C++ :int main (void) {try { ...P+=(...)... }

try signifie que le bloc est candidat pour attraper une exception lancée par une fonction exécutée directement ou indirectement dans le bloc.

Page 12: Structures de données IFT-10541 Abder Alikacem Gestion des exceptions Département dinformatique et de génie logiciel Édition Septembre 2009

Structure de contrôle throw/...try/catch

Le bloc doit être suivi d ’au moins un gestionnaire d ’exception qui récupère l ’expression (exp) lancée par une exception pour appliquer un traitement gérant cette exception.

Syntaxe C++ :int main (void) {try { ...P+=(...)... }catch (char* msg) {...}

Page 13: Structures de données IFT-10541 Abder Alikacem Gestion des exceptions Département dinformatique et de génie logiciel Édition Septembre 2009

Structure de contrôle throw/...(try/catch)

int main (void) {try { ...P+=(...)... }catch (char* msg) {...}...}

template <class X>

pile<X>& pile<X>:: operator+= (const X& e){...

elsethrow "débordement de pile";

}

1

2

Page 14: Structures de données IFT-10541 Abder Alikacem Gestion des exceptions Département dinformatique et de génie logiciel Édition Septembre 2009

Attraper une exception throw/...try/catch

Lorsqu’une exception est lancée, c ’est l ’expression exp qui est lancée. Ensuite, commence la recherche du premier bloc try actif rencontré en remontant la pile des appels à partir de l ’appel de la fonction qui a déclenché l ’exception.

Puis, on recherche le premier gestionnaire d ’exception (catch (T)) dont le type T appelé type du gestionnaire, est compatible avec le type de exp. Le contrôle est alors passé à la première instruction du bloc du gestionnaire de type compatible.

Lorsque l ’exécution de ce gestionnaire se termine alors le contrôle est passé à la première instruction qui suit la structure try/catch

Page 15: Structures de données IFT-10541 Abder Alikacem Gestion des exceptions Département dinformatique et de génie logiciel Édition Septembre 2009

Exception non attrapée ?throw/...try/catch

Si le type du premier gestionnaire rencontré est incompatible, le compilateur cherche un type de gestionnaire compatible dans les gestionnaires suivants (avec éventuellement remontée dans la pile des appels). Si aucun gestionnaire de type compatible est trouvé alors le compilateur exécutera automatiquement l ’instruction terminate.

La compatibilité de types est étudié selon les compatibilités standard du langage C++.

Page 16: Structures de données IFT-10541 Abder Alikacem Gestion des exceptions Département dinformatique et de génie logiciel Édition Septembre 2009

Instructions throw; catch(…)

int main (void) {try { ...P+=(...)... }catch (char* msg) {...}catch (int n) {...}catch (...) {

return 1;}

Plusieurs catch peuvent apparaître après un try afin de recevoir et traiter plusieurs types d'erreurs. L'expression catch(...) permet de recevoir tous les types d'erreurs non capturés par les catch précédents.

Page 17: Structures de données IFT-10541 Abder Alikacem Gestion des exceptions Département dinformatique et de génie logiciel Édition Septembre 2009

Instruction throw;

L ’instruction throw; dans un bloc catch signifie que l ’exception reçue doit continuer sa remontée à travers la pile des appels.

int main (void) {try { ...P.DepilerNfois(z);... }catch (char* msg) {...//Traitement final}catch (...) {

return 0;}

void DepilerNfois(int& n){try { ...for (int i=1; i<=n, i++)

P.depiler();... }catch (char* msg) {n=i-1;//traitement partiel

throw; }

depiler

Page 18: Structures de données IFT-10541 Abder Alikacem Gestion des exceptions Département dinformatique et de génie logiciel Édition Septembre 2009

Instruction throw(...);

Une fonction peut spécifier dans son entête les types d ’exceptions qu’elle est en mesure de lancer au bloc appelant.

pile<X>& operator+= (const X& e) throw (char *);

throw (char *); signifie que seules les exceptions char* peuvent être lancer par l’opérateur +=

Syntaxe C++ :TR fonction (T) throw(X,Y,…);

La fonction peut lancer des exceptions de types X ou Y … ou compatibles avec ces types. Lorsque rien n’est précisé la fonction peut lancer des exceptions de n’importe quel type.

Page 19: Structures de données IFT-10541 Abder Alikacem Gestion des exceptions Département dinformatique et de génie logiciel Édition Septembre 2009

Instruction throw( );

Une fonction peut spécifier dans son entête qu’aucune exception ne peut être lancée au bloc appelant.

Syntaxe C++ :

TR fonction (T) throw( );

Aucune exception en être lancée par la fonction

Normalisation dans l ’entête des méthodes. Contrôle à la compilation.

Page 20: Structures de données IFT-10541 Abder Alikacem Gestion des exceptions Département dinformatique et de génie logiciel Édition Septembre 2009

Conclusion throw/try/catch

Le mécanisme de gestion des exception codée à l ’aide de la structure de contrôle throw/try/catch implémente un moyen de passer d ’un point de l ’exécution d ’un programme qui présente une anomalie à un autre qui traite cette anomalie. Ce passage est accompagné d ’un transfert d ’informations (exp). Ce saut d ’exécution s ’apparente à un appel de fonction avec passage d ’un argument, sauf que la portion de code cible de ce passage est inconnue à la compilation.

Page 21: Structures de données IFT-10541 Abder Alikacem Gestion des exceptions Département dinformatique et de génie logiciel Édition Septembre 2009

Solution objet

throw objetExemple : throw PilePleine (…);

Appel d ’un constructeur

La fonction dans laquelle survient un dysfonctionnement lance une exception.

Chaque exception est modélisée par une classe. Exemple : class PbPilePleine

Il est intéressant de créer des types spéciaux pour gérer les exceptions car cela permet de faire remonter une exp plus complexe (plus d ’informations) et cela augmente la lisibilité et la maintenance de l ’application.

Page 22: Structures de données IFT-10541 Abder Alikacem Gestion des exceptions Département dinformatique et de génie logiciel Édition Septembre 2009

Exemple en C++

template <class X>pile<X>& pile<X>:: operator+= (const X& e){ if (indexsommet+1 <maximum) {

indexsommet+=1; t[indexsommet]=e;

return (*this); }

else

}

template <class X>class pile{ public : ... private :

X * espace;int IndexSommet;int maximum;

};

throw PbPilePleine(maximum);

Appel d ’un constructeur

Page 23: Structures de données IFT-10541 Abder Alikacem Gestion des exceptions Département dinformatique et de génie logiciel Édition Septembre 2009

Classes gérant les exceptions

// Déclaration des gestionnaires d'exception

class PbPilePleine {private :

int maxi;public :

PbPilePleine (int t) //constructeur{maxi=t; }

int GetMaxi(void) //sélecteur{return maxi;}

};

class PbPileVide {... };

Page 24: Structures de données IFT-10541 Abder Alikacem Gestion des exceptions Département dinformatique et de génie logiciel Édition Septembre 2009

Exemple : try … catch

int main (void){ string ch; pile <char> PCar(ta); cout << "\n Entrez une chaine "; cin >> ch; try{ int L=ch.length(); int i=0;

while (i<=L-1) {Pcar+=(ch[i]); i+=1;}cout << "\n Chaine inversée : ";while (! PCar.vide ( )) { cout <<PCar.sommet();

PCar.depiler ( ); } } catch (PbPilePleine P){ //P est un paramètre dont l’argument est l ’instance créée // par throw

cout << "\n PB de dépassement de taille de la pile";cout << "\n Taille maximum fixée à : "<<P.S_Maxi();

return 1; } return 0;}

Page 25: Structures de données IFT-10541 Abder Alikacem Gestion des exceptions Département dinformatique et de génie logiciel Édition Septembre 2009

Gestionnaire d ’exception universel

Il peut y avoir plusieurs gestionnaires d ’exception dans une application. Il est possible de définir un gestionnaire d ’exception universel.

Le gestionnaire d ’exceptions universel récupérera toutes les exceptions possibles, quel que soit leur type.

Syntaxe et exemple :// Déclaration des gestionnaires d'exception

try{ … }catch ( …) // traitement de toutes les autres exceptions{ cout << " Exception inattendue " ; }

Paramètre noté par trois points de suspension

Page 26: Structures de données IFT-10541 Abder Alikacem Gestion des exceptions Département dinformatique et de génie logiciel Édition Septembre 2009

Gestionnaire d ’exception universel - Exemple

// Déclaration des gestionnaires d'exception

class Erreur1 ...

try{

// calcul}catch (Erreur1 e)

{ cout << " Erreur de type "<<1;}catch ( …) // traitement de toutes les autres exceptions

{ cout << " Exception inattendue " ; }

Page 27: Structures de données IFT-10541 Abder Alikacem Gestion des exceptions Département dinformatique et de génie logiciel Édition Septembre 2009

En détail (tout objet)

Le type de ce paramètre (reçu par catch) est appelé type du gestionnaire. Ce paramètre peut être transmis par valeur ou par référence. S ’il est transmis par valeur : copie créée par le constructeur par copie.

Le destructeur est appliqué sur l ’instance créée par throw en fin de catch.

Un gestionnaire est doté d ’un et d ’un seul paramètre destiné à recevoir la valeur de l ’expression lancée.

Page 28: Structures de données IFT-10541 Abder Alikacem Gestion des exceptions Département dinformatique et de génie logiciel Édition Septembre 2009

En détail (tout objet)

Les erreurs faisant chacune l ’objet d ’une classe, on peut les organiser par catégorie et les classer par héritage.

Exemple Classe pbDePile avec deux classes dérivées PbPilePleine et PbPileVide.

On pourra alors compléter l ’entête d ’une fonction qui traite d ’une pile avec throw (pbDePile)

Un constructeur peut inclure un lancement d ’exception. C ’est d ’ailleurs, la seule solution pour gérer une erreur à la construction d ’une instance puisque le constructeur n ’a pas de type retour.

Page 29: Structures de données IFT-10541 Abder Alikacem Gestion des exceptions Département dinformatique et de génie logiciel Édition Septembre 2009

Exceptions standard du langage

• La bibliothèque standard utilise le mécanisme des exceptions du langage pour signaler les erreurs qui peuvent se produire au sein de ses fonctions.

• La STL fournit un certain nombre de classes d'exceptions standard, que les fonctions de la bibliothèque sont susceptibles de déclencher.

• Ces classes peuvent être utilisées telles quelles ou servir de classes de base à des classes d'exceptions personnalisées pour des développements propres.

Page 30: Structures de données IFT-10541 Abder Alikacem Gestion des exceptions Département dinformatique et de génie logiciel Édition Septembre 2009

Exceptions standard du langage

exception

runtime_error logic_error

héritage

bad_alloc

Page 31: Structures de données IFT-10541 Abder Alikacem Gestion des exceptions Département dinformatique et de génie logiciel Édition Septembre 2009

Hiérarchie des exceptions standard du langage

L ’exception bad_alloc lancée par les gestionnaires de mémoire lorsque l ’instruction new ou new[] est en échec, dérive de la classe exception.

Les autres  exceptions sont classées en deux grandes catégories :

1/ erreurs de logique dans l ’écriture du programme

2/ erreurs d ’exécution

La classe logic_error et ses dérivées signale des erreurs dues à la logique interne du programme. Ex: erreur sur un pointeur

La classe runtime_error et ses dérivées signale des erreurs liées à l ’environnement du programme. Ex : pas assez de mémoire

Page 32: Structures de données IFT-10541 Abder Alikacem Gestion des exceptions Département dinformatique et de génie logiciel Édition Septembre 2009

Exceptions standard du langage

Les classes gérant les exceptions dérivent toutes

de la classe exception

class exception {

public:

exception() throw(); //constructeur

exception(const exception &) throw(); //constructeur

exception& operator=(const exception &) throw();

virtual ~exception() throw(); //destructeur

virtual const char *what() const throw();

};

Page 33: Structures de données IFT-10541 Abder Alikacem Gestion des exceptions Département dinformatique et de génie logiciel Édition Septembre 2009

Exceptions standard du langage

class exception {

public: ...

virtual ~exception() throw();

virtual const char* what() const throw();

};

La méthode what retourne une chaîne de caractères décrivant la nature de l’erreur qui s’est produite.

Toutes les méthodes de la classe exception sont déclarées comme ne pouvant pas lancer d ’exception elles-mêmes. Evidemment puisqu’on est déjà en train de gérer une exception.

Page 34: Structures de données IFT-10541 Abder Alikacem Gestion des exceptions Département dinformatique et de génie logiciel Édition Septembre 2009

Erreurs de logique

class logic_error : public exception

{ public:

logic_error(const string& what_arg);

};

Cette classe contient seulement un constructeur qui prend en argument une chaîne de caractères, qui permet de donner un message explicitant l’erreur.

la classe domain_error dérive de la classe logic_error. La classe domain_error vérifie que les arguments d ’une fonction correspondent en nombre et compatibilité de types aux paramètres.

Page 35: Structures de données IFT-10541 Abder Alikacem Gestion des exceptions Département dinformatique et de génie logiciel Édition Septembre 2009

Erreurs d ’exécution

class runtime_error : public exception

{public: runtime_error(const string& what_arg);};

Par exemple la classe range_error dérive de la classe runtime_error. La classe range_error signale qu’une valeur est sortie de la plage de valeurs dans laquelle est devrait se situer.

Page 36: Structures de données IFT-10541 Abder Alikacem Gestion des exceptions Département dinformatique et de génie logiciel Édition Septembre 2009

Conclusion

Intérêt : robustesse du programme

Standardisation de la technique de report d ’erreurs

Mécanisme : POO

- Séparer code normal / gestion erreurs

- Organisation par héritage des exceptions

- Programmeur peut coder ses propres exceptions.

Page 37: Structures de données IFT-10541 Abder Alikacem Gestion des exceptions Département dinformatique et de génie logiciel Édition Septembre 2009

Exercice

Coder une classe Rationnel qui gère une exception lorsque le dénominateur est égal à zéro.

Opération : get_double qui retourne le quotient.