Les exceptions Les exceptions
Introduction Gestion erreurs Exceptions C++
Lancement Capture Syntaxe
Fonctionnement Destructeurs Standard
Les exceptions
Programmation objet
Cours n°2
Les exceptions Les exceptions
Introduction Gestion erreurs Exceptions C++
Lancement Capture Syntaxe
Fonctionnement Destructeurs Standard
Lors de l ’exécution d ’un programme, il arrive que des erreurs se présentent, non décelables à la compilation.
Exemple : c = a/b;
Le code est correct (pas d ’erreur de compilation) mais suivant la valeur de b il peut y avoir une erreur.
Il faut donc que le programme ne se poursuive pas de manière normale puisque la valeur de c n ’est pas définie.
Les exceptions Les exceptions
Introduction Gestion erreurs Exceptions C++
Lancement Capture Syntaxe
Fonctionnement Destructeurs Standard
Besoin de traitement des erreurs
Lorsqu ’un programme appelle une fonction, la
plupart du temps celle-ci effectue le travail attendu.
Mais dans certains cas, ce travail n ’est pas possible et amène des erreurs. (par ex. Avec la division quand le dividende est nul)
Quand le travail d ’une fonction ne peut être validé, il faut en avertir la fonction appelante afin qu ’elle réagisse à cet état d ’erreur.
Celle-ci peut réagir en mettant fin au programme, ou en affichant un message, etc...
Les exceptions Les exceptions
Introduction Gestion erreurs Exceptions C++
Lancement Capture Syntaxe
Fonctionnement Destructeurs Standard
Gestion simple des erreurs
Afin de connaître si une fonction ne peut pas se
terminer normalement, on peut associer à la valeur de retour un code d ’erreur.
Ex : allocation de mémoire en C via malloc() ptr = malloc(64000);
if(ptr == NULL) // code d ’erreur {
// gestion de l ’erreur }
else
// gestion normale
Les exceptions Les exceptions
Introduction Gestion erreurs Exceptions C++
Lancement Capture Syntaxe
Fonctionnement Destructeurs Standard
On voit bien que ce n ’est pas à la fonction malloc de décider quoi faire si l ’allocation mémoire échoue : c ’est au programme appelant.
Cette méthode par valeur de retour est simple, mais n ’est pas possible dans tous les cas.
Exemple : division entière int Divise(int a,int b)
{
if(b!=0) return a/b;
else
//... Quelle valeur renvoyer ????
Les exceptions Les exceptions
Introduction Gestion erreurs Exceptions C++
Lancement Capture Syntaxe
Fonctionnement Destructeurs Standard
On peut bien sur contourner la difficulté : bool Divise(int a,int b, int& q,int &r)
{
if(b) {
q=a/b;
r=a%b;
return true;
} else
return false;
}
La valeur de retour ne sert ici qu ’à tester la réussite de la fonction.
Les exceptions Les exceptions
Introduction Gestion erreurs Exceptions C++
Lancement Capture Syntaxe
Fonctionnement Destructeurs Standard
Malgré tout, dans certains cas, cette manipulation n ’est pas possible (ex : redéfinition d ’opérateurs).
De plus, rien ne garantit que le programme appelant testera bien la valeur de retour.
Le C++, comme de nombreux langages, fournit un mécanisme évolué de gestions des erreurs.
Ce mécanisme est celui des exceptions.
Les exceptions Les exceptions
Introduction Gestion erreurs Exceptions C++
Lancement Capture Syntaxe
Fonctionnement Destructeurs Standard
Exceptions en C++
• Une exception représente un fonctionnement anormal d ’une fonction/instruction .
• Son apparition est exceptionnelle et liée à certaines conditions.
• Une exception est une classe contenant
éventuellement certaines propriétés permettant d ’identifier la cause de l ’erreur.
• Un bloc d ’instructions traitant une exception est appelé gestionnaire d exceptions.
• Il existe des exceptions standard mais le programmeur peut en définir de nouvelles.
Les exceptions Les exceptions
Introduction Gestion erreurs Exceptions C++
Lancement Capture Syntaxe
Fonctionnement Destructeurs Standard
Lancement d ’une exception
Le lancement se fait par l ’instruction C++ throw.
Elle prend comme paramètre une instance d ’une classe.
Exemple : fonction division
class DIVIDE_ERROR {}; // la classe peut être vide int Divide(int a,int b)
{
if(b==0) // construction d ’une instance {
DIVIDE_ERROR d;
throw (d) ; } else return a/b;
}
Les exceptions Les exceptions
Introduction Gestion erreurs Exceptions C++
Lancement Capture Syntaxe
Fonctionnement Destructeurs Standard
Le lancement d ’une exception par throw met fin à la fonction sans renvoyer de valeur particulière.
L ’instance de classe d ’exception lancée par throw peut comporter des paramètres renseignant la cause de l ’exception.
Class DIVIDE_ERROR {
public:
enum DivErrType
{DividendeNul,TropGrand,TropPetit} Type;
DIVIDE_ERROR(DivErrType d):Type(d){};
};
Les exceptions Les exceptions
Introduction Gestion erreurs Exceptions C++
Lancement Capture Syntaxe
Fonctionnement Destructeurs Standard
Capturer une exception
Si le programme appelant ne fait rien, le lancement d ’une exception appelle la fonction standard abort qui met fin au programme.
Note : sous Borland C++ la fonction abort affiche
« Abnormal program termination » et termine le programme brutalement.
Une fonction « sensible », pouvant déclencher une exception, doit donc être surveillée lors de son
exécution : un gestionnaire d ’exception doit être mis en place.
Les exceptions Les exceptions
Introduction Gestion erreurs Exceptions C++
Lancement Capture Syntaxe
Fonctionnement Destructeurs Standard
Syntaxe des gestionnaires d ’exceptions
Un bloc d ’instruction « sensible » est placé dans un bloc try (essayer).
try {
c=Divise(a,b);
}
Ce qui indique au compilateur la surveillance de ce bloc, et la détection éventuelle d ’exceptions.
Un bloc try doit être suivi d ’un ou plusieurs gestionnaires d ’exceptions.
Les exceptions Les exceptions
Introduction Gestion erreurs Exceptions C++
Lancement Capture Syntaxe
Fonctionnement Destructeurs Standard
Un gestionnaire d ’exception se trouve dans un bloc d ’instructions précédés du mot catch.
Plusieurs blocs catch peuvent se suivre, chacun associé à un type d ’exception.
Une instruction catch prend en paramètre une instance d ’une classe d ’exception.
catch(DIVIDE_ERROR d) {
cerr<<" \nDivision impossible.\n ";
}
Les exceptions Les exceptions
Introduction Gestion erreurs Exceptions C++
Lancement Capture Syntaxe
Fonctionnement Destructeurs Standard
Exemple avec plusieurs gestionnaires : try { //... Instructions à surveiller}
catch( type_exection1 t1) {
//... Gestionnaire 1 }
catch(type_exception2 t2) {
//.... Gestionnaire 2 }
catch(...) {
// gestionnaire pour ttes exceptions }
Les exceptions Les exceptions
Introduction Gestion erreurs Exceptions C++
Lancement Capture Syntaxe
Fonctionnement Destructeurs Standard
Syntaxe à respecter (C++)
• Un bloc try doit toujours être suivi d ’un bloc catch.
• Un bloc catch est toujours placé entre { } , même s ’il est vide.
• Un bloc catch doit être précédé d ’un bloc try ou d ’un autre bloc catch
• catch(...) capture tout type d ’exceptions non capturées par les blocs précédents.
Les exceptions Les exceptions
Introduction Gestion erreurs Exceptions C++
Lancement Capture Syntaxe
Fonctionnement Destructeurs Standard
Principe de fonctionnement des exceptions
Pas d ’Exception générée
Bloc try
Suite du programme
Instructions 1er gestionnaire
Instructions 2e gestionnaire
Instructions ne gestionnaire
e est de type 1 ?
e est de type 2 ?
e est de type n ?
oui
oui
oui
non
non
non
Fin du programme
Exception e générée
Les exceptions Les exceptions
Introduction Gestion erreurs Exceptions C++
Lancement Capture Syntaxe
Fonctionnement Destructeurs Standard
Exceptions, Constructeurs et Destructeurs Toute variable locale au bloc try sera
systématiquement détruite lors du bloc catch.
La pile est dépilée pour revenir à l ’état précédent le bloc try.
Il faut s ’assurer que la recopie d ’un objet exception se passe bien (définition d ’un constructeur par recopie si besoin est) car l ’instance de la classe d ’exception est souvent passée par valeur.
Les exceptions Les exceptions
Introduction Gestion erreurs Exceptions C++
Lancement Capture Syntaxe
Fonctionnement Destructeurs Standard
Quelques exceptions standard bad_cast
Lancée quand l ’opérateur dynamic_cast ne parvient pas à effectuer une conversion de type sur une
référence.
xalloc, bad_alloc
Lancée quand l ’opérateur new ne peut allouer la mémoire demandée.
bad_typeid , xmsg
Exceptions de la bibliothèque standard
Les exceptions Les exceptions
Introduction Gestion erreurs Exceptions C++
Lancement Capture Syntaxe
Fonctionnement Destructeurs Standard
Assertions
Souvent, une méthode nécessite une précondition pour fonctionner correctement.
Exemple : opérateur [] dans une chaîne Or le test systématique peut être très pénalisant.
On peut utiliser une assertion, ce qui permet de faire un test en mode debug et non en mode release.
Voir la macro std::assert définie dans <assert>
Introduction à la programmation par contrat
Les exceptions Les exceptions
Introduction Gestion erreurs Exceptions C++
Lancement Capture Syntaxe
Fonctionnement Destructeurs Standard
Prochain cours :
Utilisation des exceptions L'idiome RAII
A la semaine prochaine !