16
Page de garde C++ Les exceptions [email protected] Maîtrise d’informatique Février 2002

Page de garde C++ Les exceptions [email protected] Maîtrise dinformatique Février 2002

Embed Size (px)

Citation preview

Page 1: Page de garde C++ Les exceptions Yannis.BRES@cma.inria.fr Maîtrise dinformatique Février 2002

Page de garde

C++Les exceptions

[email protected]

Maîtrise d’informatiqueFévrier 2002

Page 2: Page de garde C++ Les exceptions Yannis.BRES@cma.inria.fr Maîtrise dinformatique Février 2002

Les exceptions

Les exceptions

Les exceptions permettent de déléguer le traitement d’une situation exceptionelle à un gestionnaire d’exception (handler) adéquat en amont dans la pile d’exécution.

Une exception peut-être de n’importe quel type (pas nécessairement un descendant d’une classe similaire à java.lang.Throwable), y compris un type primitif (int, char *, …).

Section protégée (bloc try) et gestionnaires (blocs catch) :

try { …}catch ( exception_declaration1 ) { …}[ catch ( exception_declaration2 ) { … }…]

Lancement d’une exception par le mot-clef throw :

throw expression;

Page 3: Page de garde C++ Les exceptions Yannis.BRES@cma.inria.fr Maîtrise dinformatique Février 2002

Les exceptions : flot de contrôle

Les exceptions : flot de contrôle

Lorsqu’une exception est lancée :

1 Les portées emboîtées et les appels de méthodes empilés sont analysées/dépilés jusqu’à la découverte d’un bloc catch ; les objets partiellement ou complètement créés mais non encore détruits des portées visitées sont détruits de manière adéquate dans l’ordre inverse de leur création, de même que les tableaux d’objets.

2 Les déclarations de type d’exception géré par les blocs catch sont analysées dans l’ordre. Le cas échéant, le contrôle est donné au premier bloc catch dont le type concorde. Ce bloc peut lancer une nouvelle exception ou relancer la même exception par un simple : throw;Si aucun des blocs catch successifs n’est satisfaisant, on continue à l’étape 1.

3 Si aucun bloc catch satisfaisant n’est trouvé, ou si une exception survient durant le dépilement, la fonction prédéfinie terminate() est appelée (son comportement par défaut est d’appeler abort()).

Page 4: Page de garde C++ Les exceptions Yannis.BRES@cma.inria.fr Maîtrise dinformatique Février 2002

Les exceptions : flot de contrôle

Les exceptions : flot de contrôle

Le mot-clef try ne modifie pas le flot de contrôle, mais détermine la portée des blocs catch.

Si aucune exception n’est lancée dans un bloc try, les blocs catch ne sont pas exécutés.

Le contrôle ne peut être donné à un bloc catch qu’à la suite du lancement d’une exception concordante.

Les types reconnus par les blocs catch doivent être correctement ordonnés (les types les plus spécifiques en premier).

Il est possible de capturer n’importe quel type d’exception en utilisant les "ellipses" :

catch ( ... ) { …}On ne peut alors pas référencer l’exception reçue (puisqu’on ne connaît strictement rien de son type), mais on peut toujours la relancer avec :

throw;

Le lancement d’une exception déroute de manière irréversible le flot de contrôle : il est impossible de reprendre l’exécution à la "continuation" de l’instruction throw.

Page 5: Page de garde C++ Les exceptions Yannis.BRES@cma.inria.fr Maîtrise dinformatique Février 2002

Les exceptions : flot de contrôle

Les exceptions : exemple

class MathError { public: virtual const char * GetMessage();};

class OverflowError: public MathError{ public: const char * GetMessage();};

class DivisionByZeroError: public MathError{ public: const char * GetMessage();};

Page 6: Page de garde C++ Les exceptions Yannis.BRES@cma.inria.fr Maîtrise dinformatique Février 2002

Les exceptions : flot de contrôle

Les exceptions : exemple

try{ … throw DivisionByZeroError(); …}catch ( const OverflowError& e ){ // ici, on traite les erreurs de dépassement de capacité}catch ( const DivisionByZeroError& e ){ // ici, on traite les erreurs de division par zéro}catch ( const MathError& e ){ // ici, on traite les erreurs mathématiques génériques qui ne // sont ni des dépassement de capacité, ni des div. par zéro}

Page 7: Page de garde C++ Les exceptions Yannis.BRES@cma.inria.fr Maîtrise dinformatique Février 2002

Les exceptions : terminate()

Les exceptions : terminate()

La fonction prédéfinie terminate() est appelée lorsqu’aucun bloc catch adéquat n’a été trouvé, lorsqu’une exception a été lançée lors du déroulement de la pile ou lorsque celle-ci est corrompue.

Par défaut, terminate() invoque abort().

L’appel de terminate() peut-être remplacé par celui d’un autre gestionnaire avec :

terminate_handler set_terminate( terminate_handler ph ) throw();

Avec terminate_handler défini par :

typedef void ( *terminate_handler )();

set_terminate( … ) renvoie le gestionnaire précédemment installé (possibilité de chaînage).

Les gestionnaires "terminate" ne doivent jamais faire de return (quelle serait leur continuation ?).

Page 8: Page de garde C++ Les exceptions Yannis.BRES@cma.inria.fr Maîtrise dinformatique Février 2002

Les exceptions : déclarations d’exceptions lançables

Les exceptions : déclarations d’exceptions lançables

Les fonctions peuvent éventuellement déclarer la liste des exceptions qu’elles sont susceptibles de lancer/propager, en spécifiant, avant le point-virgule, l’accolade ouvrante, =0, … :

throw ( type1[, type2[, ...]] ) // throws en Java

Une liste vide indique que la fonction ne lance/propage pas d’exception.

L’absence de telle déclaration indique que la fonction est susceptible de lancer/propager n’importe quel type d’exception.

Si une fonction lance/propage une exception ne faisant pas partie des exceptions déclarée, la fonction prédéfinie unexpected() est invoquée (son comportement par défaut est d’appeler abort()).Une telle violation de la déclaration ne peut être détectée, dans le cas général, que lors de l’exécution, du fait de l’utilisation de fonctions externes C, de la nécessiter de tout recompiler en cas de modification, …Pour ces mêmes raisons, la liste de déclaration d’exceptions ne fait pas partie de la signature d’une méthode.

Page 9: Page de garde C++ Les exceptions Yannis.BRES@cma.inria.fr Maîtrise dinformatique Février 2002

Les exceptions : unexpected()

Les exceptions : unexpected()

La fonction prédéfinie unexpected() est appelée lorsqu’une exception ne faisant pas partie de la liste de déclaration est lancée/propagée.

Par défaut, unexpected() invoque abort().

L’appel de unexpected() peut-être remplacé par celui d’un autre gestionnaire avec :

unexpected_handler set_unexpected( unexpected_handler uh ) throw();

Avec unexpected_handler défini par :

typedef void ( * unexpected_handler )();

set_unexpected( … ) renvoie le gestionnaire précédemment installé (possibilité de chaînage).

Les gestionnaires "unexpected" ne doivent jamais faire de return (quelle serait leur continuation ?).

MSVC++ 6 & 7 : non supporté.

Page 10: Page de garde C++ Les exceptions Yannis.BRES@cma.inria.fr Maîtrise dinformatique Février 2002

Hiérarchie des exceptions

Hiérarchie des exceptions

Même si les exceptions ne sont pas nécessairement des objets, la librairie standard propose une hiérarchie de classe qu’il est préconisé de respecter (dans le namespace std).

La classe mère de toutes les exceptions :

class exception{ public: exception() throw(); exception( const exception& right ) throw(); exception& operator=( const exception& right ) throw(); virtual ~exception() throw(); virtual const char * what() const throw();};

what() renvoie une chaîne de caractères décrivant l’exception.

Page 11: Page de garde C++ Les exceptions Yannis.BRES@cma.inria.fr Maîtrise dinformatique Février 2002

Hiérarchie des exceptions

Hiérarchie des exceptions

Les classes dérivées de exception :

class logic_error: public exception; class invalid_argument: public logic_error; class out_of_range: public logic_error; class length_error: public logic_error; class domain_error: public logic_error;class runtime_error: public exception; class range_error: public runtime_error; class overflow_error: public runtime_error; class underflow_error: public runtime_error;

Page 12: Page de garde C++ Les exceptions Yannis.BRES@cma.inria.fr Maîtrise dinformatique Février 2002

Les exceptions : allocation mémoire

Les exceptions : allocation mémoire

Les instances d’exceptions à lancer peuvent être créées :

dans le tas :

throw new Exception( … );

Eventuels problèmes de mémoire non disponible !

dans la pile (objet local) :

throw Exception( … );

L’objet exception ainsi lancé ne devrait plus être disponible lorsque le bloc catch y accède, puisque la pile a été déroulée. En fait, le bloc catch va recevoir une copie de l’exception, à un emplacement garanti accessible.

Néanmoins, dans les objets exceptions, veiller à ne pas stocker de pointeurs/références vers des objets locaux qui ne seront plus disponibles une fois la pile déroulée !

Page 13: Page de garde C++ Les exceptions Yannis.BRES@cma.inria.fr Maîtrise dinformatique Février 2002

Les exceptions : catch par copie ou par référence ?

Les exceptions : catch par copie ou par référence ?

Une exception lancée par

throw Exception( … );

Pourra à la fois être traitée par un bloc catch attendant un objet passé par valeur :

Le passage par valeur nécessite des copies supplémentaires, voire des conversions de types : seul le passage par référence permet d’utiliser au maximum le polymorphisme des exceptions.

catch ( [const] Exception e )

Ou par un bloc catch attendant un objet passé par adresse (référence) :

catch ( [const] Exception& e )

Modifier une exception attrapée par valeur avant de la relancer ne sert à rien…

Page 14: Page de garde C++ Les exceptions Yannis.BRES@cma.inria.fr Maîtrise dinformatique Février 2002

Les function-try blocks

Les function-try blocks

Pour une séparation maximale du code "normal" et du code de traitement d’exceptions, le corps d’une fonction peut être un bloc try (avec son ou ses blocs catch afférents) direct :

int main()try{ …}catch ( … ){}…

MSVC++ 6 : non supporté.

MSVC++ 7 : supporté.

Page 15: Page de garde C++ Les exceptions Yannis.BRES@cma.inria.fr Maîtrise dinformatique Février 2002

Les function-try blocks

Les function-try blocks

Cela est surtout nécessaire pour attraper les exceptions lancées par les évaluations des expressions des listes d’initialisations de constructeurs :

A::A( … )try : membre1( expr1 ), membre2( expr2 ), …{ // corps du constructeur}catch ( … ){ …}…

Sans le principe des function-try blocks, les exceptions lancées par expr… ne pourraient être traitées par le constructeur.

Page 16: Page de garde C++ Les exceptions Yannis.BRES@cma.inria.fr Maîtrise dinformatique Février 2002

Exceptions et libérations de ressources

Exceptions et libérations de ressources

Evitez la duplication de code de libération de ressources, comme dans :

acquérir_la_ressource;try{ utiliser_la_ressource;}catch ( ... ){ libérer_la_ressource; throw;}libérer_la_ressource;

Imaginez s’il y avait un grand nombre de ressources à acquérir et libérer !

Utilisez plutôt des objets, dont la destruction est garantie même en cas de déroutement à la suite d’une exception :

« L’acquisition d’une ressource est une initialisation,la libération d’une ressource est une destruction. »