try - catch en C++

try - catch en C++ - C++ - Programmation

Marsh Posté le 08-05-2005 à 10:51:27    

Bonjour,
 
je débute un peu avec le C++ et je me demandais si il était possible de faire de la gestion d'erreur en try-catch qui reprenne l'éxecution du code après le throw, et pas après le bloc catch.
 
Exemple :
 
Le but serait ici que le bloc catch n'affiche qu'un message d'avertissement si erreur.code est 0 et que l'exécution continue normalement, et qu'il quitte le programme si erreur.code vaut 1.
 
Code :
 

Citation :


....
 
struct Erreur
{
        string message;
        int code;
};
 
....
string compresse(const string& data, char flag) throw (Erreur)
{
                ......
                                        if (data2[i]=='a')
                                        {
                                                Erreur er1;
                                                er1.message ="avertissement";
                                                er1.code =0;
                                                throw er1;
                                        }
                          .....
                  return data2;
}
 
string decompresse(const string& rledata, char flag) throw (Erreur)
{
   ....
                        if (rledata2[i+1]==flag)
                        {
                                Erreur er2;
                                er2.message="erreur : flag apres flag";
                                er2.code=1;
                                throw er2;
                        }
        .....  
        return rledata2;
}
 
                                 
int main()
{
       ....
        try
        {
                string str2(compresse(str1,'#'));
                // le programme doit s'exécuter jusqu'ici, même si compresse lève une exception
                ....
                string str3(decompresse(str2,'#'));
                // mais plus là (si decompresse lève une exception)
        }
        catch (Erreur erreur)
        {
                if (erreur.code==0)
                {
                        cout <<erreur.message<<endl;
                        // LA JUSTE UN AVERTISSEMENT
                }
                else
                {
                        cout <<erreur.message<<endl;
                        return 0; // pour quitter le programme
                         
                }
        }
}


 
Voilà merci d'avance pour vos réponses et bon dimanche!
 
A+

Reply

Marsh Posté le 08-05-2005 à 10:51:27   

Reply

Marsh Posté le 08-05-2005 à 10:59:54    

déjà, ta classe d'exception, tu là fais hérité de quelque chose dans <stdexcep>
 
ensuite, tu attrapes l'exception par &
 
et ne déclare pas le type d'exception lancé
 
pour finir : n'inclue pas de code, contente toi de définir différentes classes d'exception

Reply

Marsh Posté le 08-05-2005 à 11:52:29    

Code :
  1. #include <stdexcept>
  2. #include <string>
  3. namespace Xixor
  4. {
  5.   class ErreurCompression : public std::runtime_error
  6.   {
  7.   public:
  8.     explicit ErreurCompression(const std::string& );
  9.   };
  10.   class ErreurDecompression : public std::runtime_error
  11.   {
  12.   public:
  13.     explicit ErreurDecompression(const std::string& );
  14.   };
  15.   std::string compresse(const std::string& );
  16.   std::string decompresse(const std::string& );
  17. }
  18. namespace Xixor
  19. {
  20.   ErreurCompression::ErreurCompression(const std::string& msg)
  21.     : std::runtime_error(msg)
  22.   { }
  23.   ErreurDecompression::ErreurDecompression(const std::string& msg)
  24.     : std::runtime_error(msg)
  25.   { }
  26.   std::string compresse(const std::string& s)
  27.   {
  28.     if(s.empty())
  29.       throw ErreurCompression("La chaîne est vide" );
  30.     return "blah";
  31.   }
  32.   std::string decompresse(const std::string& s)
  33.   {
  34.     if(s.empty())
  35.       throw ErreurDecompression("La chaîne est vide" );
  36.     return "blih";
  37.   }
  38. }
  39. #include <iostream>
  40. int main()
  41. {
  42.   try
  43.     {
  44.       Xixor::compresse("foo" );
  45.       Xixor::compresse("" );
  46.     }
  47.   catch(const Xixor::ErreurCompression& ex)
  48.     {
  49.       std::cerr << "Une erreur s'est produite lors de la compression : "
  50.  << ex.what() << '\n';
  51.     }
  52.   try
  53.     {
  54.       Xixor::compresse("foo" );
  55.       Xixor::decompresse("" );
  56.     }
  57.   catch(const Xixor::ErreurDecompression& ex)
  58.     {
  59.       std::cerr << "Une erreur s'est produite lors de la decompression : "
  60.  << ex.what() << '\n';
  61.     }
  62.   catch(const Xixor::ErreurCompression& ex)
  63.     {
  64.       std::cerr << "Une erreur s'est produite lors de la compression : "
  65.  << ex.what() << '\n';
  66.     }
  67.   try
  68.     {
  69.       Xixor::compresse("foo" );
  70.       Xixor::decompresse("" );
  71.     }
  72.   catch(const std::exception& ex)
  73.     {
  74.       std::cerr << "Une erreur s'est produite : "
  75.  << ex.what() << '\n';
  76.     }
  77. }

pour bien faire


Message édité par Taz le 08-05-2005 à 22:17:41
Reply

Marsh Posté le 08-05-2005 à 13:57:49    

OK merci!
 
Je regarderai tout ça en détail ce soir !

Reply

Marsh Posté le 08-05-2005 à 22:06:04    

Citation :

 catch(Xixor::ErreurCompression& ex)


 
pas de const ? [:le kneu]


---------------
NP: HTTP Error 764 Stupid coder found
Reply

Marsh Posté le 08-05-2005 à 22:17:08    

si tu en veux ...
mais pour rendre ça drôle, je devrais jeter des exceptions à base de pointeurs :D

Reply

Marsh Posté le 08-05-2005 à 22:23:18    

en fait, note que comme l'objet de l'exception est en ta possession, tu peux t'en servir comme tu veux. Par exemple, faire
 
ex.message = "Meilleur message de diagnostique";
throw;
 
ce que tu t'interdis avec le const.

Reply

Marsh Posté le 08-05-2005 à 22:31:19    

mais je te sens joueur ce soir : comment ferais-tu pour centraliser la gestion des exceptions, pour ne pas à avoir à taper plusieurs fois toutes la même série de bloc catch ?

Reply

Marsh Posté le 09-05-2005 à 00:18:13    

A la demande express de mon grand ami push qui me rapelle fort justement et avec le tact qui lui est coutumier que j'ai posté ici [:god]
 

Taz a écrit :

mais je te sens joueur ce soir


 
ah mais pas du tout, il ne fallait pas prendre ma question comme etant un défi mais plutot comme l'expression de ma surprise, etant donné que je t'ai souvent vu brandir bien haut l'etendart du "const machin &" dans la gestion d'exception
 
 

Citation :

comment ferais-tu pour centraliser la gestion des exceptions, pour ne pas à avoir à taper plusieurs fois toutes la même série de bloc catch ?


 
votre question ne m'est pas tres claire mon cher [:klem3i1] et depuis 6 mois que je fais du C de bagnard, les exceptions, hein, je vais finir par meme pu trop de quoi il en retourne


Message édité par chrisbk le 09-05-2005 à 00:18:29

---------------
NP: HTTP Error 764 Stupid coder found
Reply

Marsh Posté le 09-05-2005 à 00:41:27    

comment tu ferais pour factoriser le traitement d'erreur ? dans l'exemple, j'ai deux try, et à chaque fois, plusieurs catch. Et ça fait plein de code en double pour traiter l'exception.

Reply

Marsh Posté le 09-05-2005 à 00:41:27   

Reply

Marsh Posté le 09-05-2005 à 01:09:12    

bah jbricolerais un truc a base de fonctions, vu que la seule chose qui change c'est le block try. M'enfin ne me fait pas trop passer pour un con trop longtemps et donne nous ta fine reponse [:god]


---------------
NP: HTTP Error 764 Stupid coder found
Reply

Marsh Posté le 09-05-2005 à 01:12:37    

Code :
  1. void gestion_erreur(const char* file, int line, const std::string& msg)
  2.   {
  3.     try
  4.       {
  5.         throw;
  6.       }
  7.     catch(Xixor::ErreurDecompression& ex)
  8.       {
  9.         std::cerr << file << ':' << line
  10.                   << " Une erreur s'est produite lors de la compression : "
  11.                   << '(' << ex.what() << " ). "
  12.                   << msg << '\n';
  13.       }
  14.     catch(Xixor::ErreurCompression& ex)
  15.       {
  16.         std::cerr << file << ':' << line
  17.                   << " Une erreur s'est produite lors de la decompression : "
  18.                   << '(' << ex.what() << " ). "
  19.                   << msg << '\n';
  20.       }
  21.   }
  22. #define GESTION_ERREUR(MSG) Xixor::gestion_erreur(__FILE__, __LINE__, MSG)


 

Code :
  1. try
  2.     {
  3.       Xixor::compresse("foo" );
  4.       Xixor::decompresse("" );
  5.     }
  6.   catch(...)
  7.     {
  8.       GESTION_ERREUR("Ça suffit maintenant !" );
  9.     }


 
et hop, un répartisseur d'exception, sans dynamic_cast :)

Reply

Marsh Posté le 09-05-2005 à 01:18:35    

moué [:ohtusais]


---------------
NP: HTTP Error 764 Stupid coder found
Reply

Marsh Posté le 09-05-2005 à 01:35:53    

fais des cauchemards !

Reply

Marsh Posté le 09-05-2005 à 11:01:13    

C'est quoi ce complot hérétique nocturne contre la religion C++ ?
C'etait pour montrer à chrisbk qu'il existe aussi du C++ de bagnard ? :D

Reply

Marsh Posté le 09-05-2005 à 11:11:47    

chui clairement pas fan de cette bidouille [:ohtusais] et la macro n'est pas la pour arranger les choses [:ohtusais]
 
fab >> du C++ de bagnard je connais, j'en ai meme fait a mes debuts [:marc] (du beau C with classes [:marc])


---------------
NP: HTTP Error 764 Stupid coder found
Reply

Marsh Posté le 09-05-2005 à 11:14:04    

spa une bidouille. Et la macro, elle set à pas grand chose.
 
Le dernier conseil du jour : ne jamais relancé une exception avec un 'throw e;'. Toujours utilisé 'throw;'. Sinon tu fous en l'air le polymorphisme.

Reply

Marsh Posté le 09-05-2005 à 11:22:42    

Et à quoi te sert le polymorphisme dans ta bidouille ? [:itm] Et à quoi ça te sert de faire hériter tes classes d'exceptions de std::exception (ou une de ces filles) ? [:itm]
Sans compter que la moindre modification dans le bloc try ou dans le nom des classes d'exceptions t'oblige à tout recoder ...
 

Reply

Marsh Posté le 09-05-2005 à 11:26:26    

...
 
réfléchi d'abord à mon message précédent. En quoi
 

Code :
  1. catch(My::Exception& e)
  2. {
  3.   e.add_info("shit can happen" );
  4.   throw e;
  5. }


 
est un bug alors que
 

Code :
  1. catch(My::Exception& e)
  2. {
  3.   e.add_info("shit can happen" );
  4.   throw;
  5. }


 
est correcte ?

Reply

Marsh Posté le 09-05-2005 à 11:27:59    

OK pour ça ...

Reply

Marsh Posté le 09-05-2005 à 11:31:05    

pourquoi ?

Reply

Marsh Posté le 09-05-2005 à 11:33:53    

++fab a écrit :

Et à quoi te sert le polymorphisme dans ta bidouille ? [:itm] Et à quoi ça te sert de faire hériter tes classes d'exceptions de std::exception (ou une de ces filles) ? [:itm]
Sans compter que la moindre modification dans le bloc try ou dans le nom des classes d'exceptions t'oblige à tout recoder ...


 
 
cet argument m'a l'air quand meme sacrement foireux [:marc]


---------------
NP: HTTP Error 764 Stupid coder found
Reply

Marsh Posté le 09-05-2005 à 11:34:48    

ma remarque à 11h22 n'etait pas du tout destiné à ton dernier conseil du jour, mais à ta bidouille.
Qu'est ce que ça apporte par rapport à ce que tu avais écrit plus haut ? (en bien)
# try
#     {
#       Xixor::compresse("foo" );
#       Xixor::decompresse("" );
#     }
#   catch(const std::exception& ex)
#     {
#       std::cerr << "Une erreur s'est produite : "
#         << ex.what() << '\n';
#     }

Reply

Marsh Posté le 09-05-2005 à 11:42:06    

chrisbk a écrit :

cet argument m'a l'air quand meme sacrement foireux [:marc]


Le nom des classes d'exceptions, c'est qqchose que je change environ 3 ou 4 fois, mais c'est une lacune personnelle. J'ai toujours tendance à sous-estimer l'importance d'une conception tot dans le projet de la hiérarchie des classes d'exception. Malgré les conseils du BS  [:petrus75]

Reply

Marsh Posté le 09-05-2005 à 11:51:46    

ben tu peux centraliser ton code de gestion d'erreur. Notemment si tu dois prendre des décisions (genre ouvrir un message d'erreur). Je te dis pas qu'il faut utiliser que ça, je te dis qu'il y a de la place pour les deux.

Reply

Marsh Posté le 09-05-2005 à 15:02:25    

alors vous abandonnez ?
 

Code :
  1. #include <stdexcept>
  2. #include <string>
  3. #include <iostream>
  4. namespace My
  5. {
  6.   class Exception : public std::exception
  7.   {
  8.     std::string info;
  9.   public:
  10.     virtual void add_info(const std::string& info)
  11.     {
  12.       this->info += info;
  13.     }
  14.     virtual const char* what() const throw()
  15.     {
  16.       return this->info.c_str();
  17.     }
  18.     virtual ~Exception() throw() { }
  19.   };
  20.   class BadException : public Exception
  21.   {
  22.   public:
  23.     virtual ~BadException() throw() { }
  24.   };
  25. }
  26. int main()
  27. {
  28.   try
  29.     {
  30.       try
  31. {
  32.   throw My::BadException();
  33. }
  34.       catch(My::Exception& e)
  35. {
  36.   e.add_info("blah" );
  37.   throw e; // ou throw; ?
  38. }
  39.     }
  40.   catch(My::BadException& e)
  41.     {
  42.       std::cerr << "BadException " << e.what() << '\n';
  43.     }
  44.   catch(My::Exception& e)
  45.     {
  46.       std::cerr << "Exception " << e.what() << '\n';
  47.     }
  48. }

sans compiler, vous pensez que ça donne quoi ça ?

Reply

Marsh Posté le 09-05-2005 à 15:38:41    

"Exception" (sans compiler)

Reply

Marsh Posté le 09-05-2005 à 15:49:59    

et pourquoi ?

Reply

Marsh Posté le 09-05-2005 à 15:54:57    

parce que l'exception jetee est une My::Exception par lien polymorphique mais lorsque on fait trow e; on perd l'informartion sur le caractere dynamique du type de l'exception (pas sur :ange:, et pas sur que ca ve dire qulequechose) qui devien My::Exception

Reply

Marsh Posté le 09-05-2005 à 15:55:29    

Taz a écrit :

et pourquoi ?


 
throw; ça propage l'exception.
 
throw e; ça déclenche une exception du type statique de e. e construit par [edit]COPY[\edit]  constructor.


Message édité par ++fab le 09-05-2005 à 16:11:48
Reply

Marsh Posté le 09-05-2005 à 15:56:37    

throw; préserve le type dynamique de e.

Reply

Marsh Posté le 09-05-2005 à 15:58:37    

bon ça va. la clef étant 'type statique'.

Reply

Marsh Posté le 09-05-2005 à 16:05:40    

plus précisément, lors d'un throw My::badException(), une copie temporaire est faite, et elle perdure tant qu'il y a un gestionnaire capable de traiter l'exception. Si l'affaire se termine par autre chose que throw; la copie temporaire est détruite et désallouée !

Reply

Marsh Posté le 09-05-2005 à 23:13:12    

J'ai fini par réaliser l'objectif de ton trick. Vu qu'il était enrober de glaise, je l'ai pris tel quel et j'ai cru que tu rennonçais au polymorphisme ... d'ou ma surprise.
Ton trick sert donc à réaliser une centralisation décentrée (dans le corps d'une fonction) de la gestion des exceptions. C'est un poil obfuscant à mon gout, mais ça sépare encore plus le code d'erreur du reste.
 
On pourrait peut etre s'en servir dans un cas, sans obfuscations aucune :
 
Supposons que l'on ai 2 hiérarchies de classes d'exceptions (distinctes).
On récupère habituellement les exceptions dans le plus pur style "les enfants d'abord" (pour éviter le dynamic_cast<> ). Sauf que lorsque l'on a deux hiérarchies distinctes, c'est pas évident de rendre la gestion très lisible.
A ce moment la, Taz exception's trick :
 

Code :
  1. try{/*...*/}
  2. catch(const std::exception& e)
  3. { GESTION_ERREUR1("toto" ) }
  4. catch(const nonstd::exception& e)
  5. { GESTION_ERREUR2("toto" ) }

Reply

Marsh Posté le 09-05-2005 à 23:14:55    

ben à chaque fois tu écris autant de  catch ...
 
# catch(const std::exception& e)
# { GESTION_ERREUR1("toto" ) }
# catch(const nonstd::exception& e)
# { GESTION_ERREUR2("toto" ) }
 
tu duplique à chaque fois. le but c'est foutre ça dans une fonction

Reply

Marsh Posté le 09-05-2005 à 23:15:01    

Et encore, c'est criticable puisqu'il faut faire 2 fonctions, qu'on va quand meme essayer de mettre dans le meme namespace.

Reply

Marsh Posté le 09-05-2005 à 23:16:14    

Taz a écrit :

ben à chaque fois tu écris autant de  catch ...


ben non, je prend juste la base

Reply

Marsh Posté le 09-05-2005 à 23:17:05    

bah la tu perds des informations de types, et tu dois dynamic_cast'er pour en savoir plus dans tes trucs de gestions d'erreurs.

Reply

Marsh Posté le 09-05-2005 à 23:19:40    

Regarde bien, y a 2 macros ... qui appelle chacune une fonction différente, mais ça n'apparait pas OK.

Reply

Marsh Posté le 09-05-2005 à 23:21:27    

ben alors de quoi tu parles ? c'est exactement la même chose. Je t'ai jamais dit que tu devais ne faire qu'une seule et unique fonction.

Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed