Programmation C-C++/Les exceptions/Remontée des exceptions
Les fonctions intéressées par les exceptions doivent les capter avec le mot clé catch comme on l'a vu ci-dessus. Elles peuvent alors effectuer tous les traitements d'erreurs que le C++ ne fera pas automatiquement. Ces traitements comprennent généralement le rétablissement de l'état des données manipulées par la fonction (dont, pour les fonctions membres d'une classe, les données membres de l'objet courant), ainsi que la libération des ressources non encapsulées dans des objets de classe de stockage automatique (par exemple, les fichiers ouverts, les connexions réseau, etc.).
Une fois ce travail effectué, elles peuvent, si elles le désirent, relancer l'exception, afin de permettre un traitement complémentaire par leur fonction appelante. Le parcours de l'exception s'arrêtera donc dès que l'erreur aura été complètement traitée. Bien entendu, il est également possible de lancer une autre exception que celle que l'on a reçue, comme ce peut être par exemple le cas si le traitement de l'erreur provoque lui-même une erreur.
Pour relancer l'exception en cours de traitement dans un gestionnaire d'exception, il faut utiliser le mot clé throw. La syntaxe est la suivante :
throw ;
L'exception est alors relancée, avec comme valeur l'objet que le compilateur a construit en interne pour propager l'exception. Les gestionnaires d'exception peuvent donc modifier les paramètres des exceptions, s'ils les attrapent avec une référence.
Si, lorsqu'une exception se produit dans un bloc try, il est impossible de trouver le bloc catch correspondant à la classe de cette exception, il se produit une erreur d'exécution. La fonction prédéfinie std::terminate est alors appelée. Elle se contente d'appeler une fonction de traitement de l'erreur, qui elle-même appelle la fonction abort de la bibliothèque C. Cette fonction termine en catastrophe l'exécution du programme fautif en générant une faute (les ressources allouées par le programme ne sont donc pas libérées, et des données peuvent être perdues). Ce n'est généralement pas le comportement désiré, aussi est-il possible de le modifier en changeant la fonction appelée par std::terminate.
Pour cela, il faut utiliser la fonction std::set_terminate, qui attend en paramètre un pointeur sur la fonction de traitement d'erreur, qui ne prend aucun paramètre et renvoie void. La valeur renvoyée par std::set_terminate est le pointeur sur la fonction de traitement d'erreur précédente. std::terminate et std::set_terminate sont déclaréee dans le fichier d'en-tête exception.
Exemple 9-2. Installation d'un gestionnaire d'exception avec set_terminate
[modifier | modifier le wikicode]#include <iostream>
#include <exception>
using namespace std;
void mon_gestionnaire(void)
{
cout << "Exception non gérée reçue !" << endl;
cout << "Je termine le programme proprement..."
<< endl;
exit(-1);
}
int lance_exception(void)
{
throw 2;
}
int main(void)
{
set_terminate(&mon_gestionnaire);
try
{
lance_exception();
}
catch (double d)
{
cout << "Exception de type double reçue : " <<
d << endl;
}
return 0;
}