la chaine de caractères dans std::exception

la chaine de caractères dans std::exception - C++ - Programmation

Marsh Posté le 08-09-2003 à 21:42:10    

bonjour,  
 
j'aimerais pouvoir utiliser la chaine de caractères que peut contenir std::exception.
 
j'ai vu qu'un de ses constructeurs est exception(const char* const & ) et qu'un de ses membres publics est const char * what(), mais je ne comprends pas qui doit allouer et désallouer la chaine, ou s'il y aurait plus simplement moyen d'utiliser std::string ?
 
un petit exemple svp :)
 
(j'ai essayé de regarder la définition de std::exception dans les header, j'ai rien compris ...)


---------------
-( BlackGoddess )-
Reply

Marsh Posté le 08-09-2003 à 21:42:10   

Reply

Marsh Posté le 08-09-2003 à 21:50:08    

il peut y avoir une contre indication à l'utilisation des string, mais bon, c'est préférable de les utiliser et on ne va pas tatillonner  
 
 
const char * what() const
{
  return this->msg.c_str();
}


Message édité par Taz le 08-09-2003 à 21:50:36
Reply

Marsh Posté le 08-09-2003 à 21:57:33    

je peux donc faire :
 

Code :
  1. using namespace std;
  2. try
  3. {
  4. throw exception(string("message" ));
  5. }
  6. catch (const exception & e)
  7. {
  8. string s(e.what());
  9. }


?
 
elle est détruite quand l'exception ? (l'instance de std::exception)


---------------
-( BlackGoddess )-
Reply

Marsh Posté le 08-09-2003 à 21:59:13    

j'ai aussi vu que std::exception avait un constructeur de copie, et un operator= est-ce obligatoire pour une classe d'exception ?


---------------
-( BlackGoddess )-
Reply

Marsh Posté le 08-09-2003 à 22:00:51    

try
  {
    throw my_exception("message" );
  }
  catch (const exception & e)
  {
 
   // ici tu recontruit une string
    string s(e.what());
 
// vu la signature tu peux te contenter de
   
    const char*msg=e.what();
  }  
 
 
 
pas de problèmes d'allocation, si tu veux manipueler par contre, passe par une std::string effectivement
 
 

Reply

Marsh Posté le 08-09-2003 à 22:04:44    

throw exception(string("message" )); ne fonctionnait pas en effet.
Merci  :jap:


---------------
-( BlackGoddess )-
Reply

Marsh Posté le 08-09-2003 à 22:42:28    

encore une tite question qui dévie un peu du sujet :
 
si un constructeur fait un exception, et qu'elle est gérée, est ce que le destructeur sera appelé ?


---------------
-( BlackGoddess )-
Reply

Marsh Posté le 08-09-2003 à 22:44:45    

oula c'est une histoire compliquée tout ça, une très longue histoire. je crois que tu ferais bien de t'orienter vers le Stroustrup à ce niveau là (j'ai pas vocation à taper des pages du moins pas ce soir)

Reply

Marsh Posté le 08-09-2003 à 22:52:01    

laisse moi la soirée pour t'en parler

Reply

Marsh Posté le 08-09-2003 à 23:05:22    

:)  :jap:


---------------
-( BlackGoddess )-
Reply

Marsh Posté le 08-09-2003 à 23:05:22   

Reply

Marsh Posté le 08-09-2003 à 23:23:51    

la réponse est non. l'objet n'étant pas construit, il pourrait etre désastreux d'exécuter le destructeur. par contre, les membres correctment initialisés sont détruits. l'initialisation est une bonne méthode pour avoir un comportement sain d'ailleurs
 
note le bloc try-catch fonctionnel autour du destructeur qui peu t'aider à gérer les exceptions lancées à l'initialisation des membres.
 
le problème qui apparait, c'est en cas d'allocation dynamique, il n'y a aucun moyen de libérer la mémoire en cas d'exception. que se passe t'il en effet si au cours du constructeur, quleque chose jète une exception? comment faire pour savoir quoi et quand se qui s'est passé?  le bloc try-catch fonctionnel peut t'aider, mais uniquement dans certains cas, et fastidieusement. bref, fuite de mémoire. la solution sure est donc d'encapsuler systématiquement les allocations dans des porteurs. d'ou le role tres fort des conteneurs STL qui apportent beaucoup de sécurité. c'est bon ?
 
 

Code :
  1. #include <iostream>
  2. #include <stdexcept>
  3. using namespace std;
  4. class Foo
  5. {
  6.  
  7. public:
  8.  
  9.   Foo(bool throwEx = false)
  10.   {
  11.     if(throwEx)
  12.       {
  13. throw invalid_argument("Erreur Foo" );
  14.       }
  15.     cout << "Foo()\n";
  16.   }
  17.   ~Foo()
  18.   {
  19.     cout << "~Foo()\n";
  20.   }
  21. };
  22. class Bar
  23. {
  24.   Foo f;
  25. public:
  26.  
  27.   Bar(bool throwEx)
  28.     : f(false)
  29.   {
  30.     Foo(true);
  31.     cout << "Bar()\n";
  32.   }
  33.   ~Bar()
  34.   {
  35.     cout << "~Bar()\n";
  36.   }
  37. };
  38. class Bar2
  39. {
  40.   Foo f;
  41.   Foo g;
  42.   Foo h;
  43. public:
  44.  
  45.   Bar2(bool throwEx)
  46.     : f(false), g(throwEx), h(false)
  47.   {
  48.     cout << "Bar2()\n";
  49.   }
  50.   ~Bar2()
  51.   {
  52.     cout << "~Bar2()\n";
  53.   }
  54. };
  55. class Bar3
  56. {
  57.   Foo f;
  58.   Foo g;
  59.   Foo h;
  60. public:
  61.  
  62.   Bar3(bool throwEx)
  63.     try
  64.     : f(false), g(throwEx), h(false)
  65.   {
  66.     cout << "Bar3()\n";
  67.   }
  68.   catch(const std::exception &ex)
  69.   {
  70.     cerr << "***" << ex.what() << endl;
  71.   }
  72.   ~Bar3()
  73.   {
  74.     cout << "~Bar3()\n";
  75.   }
  76. };
  77. int main()
  78. {
  79.   try
  80.     {
  81.       Foo(true);
  82.     }
  83.   catch(const std::exception &ex)
  84.     {
  85.       cerr << ex.what() << endl;
  86.     }
  87.   cout << "\n";
  88.   try
  89.     {
  90.       Bar(true);
  91.     }
  92.   catch(const std::exception &ex)
  93.     {
  94.       cerr << ex.what() << endl;
  95.     }
  96.   cout << "\n";
  97.   try
  98.     {
  99.       Bar2(true);
  100.     }
  101.   catch(const std::exception &ex)
  102.     {
  103.       cerr << ex.what() << endl;
  104.     }
  105.   cout << "\n";
  106.   try
  107.     {
  108.       Bar3(true);
  109.     }
  110.   catch(const std::exception &ex)
  111.     {
  112.       cerr << ex.what() << endl;
  113.     }
  114. }

Reply

Marsh Posté le 08-09-2003 à 23:39:17    

note aussi le fonctionnement de Bar.  
sinon je réinsiste sur la technique « acquisition par initialisation » et te conseille quand tu le peux pas l'utilisation de pointeurs intelligents (à commencer par les std::auto_ptr) qui te garantiront de ne pas laisser de fuite de mémoire en cas d'exception.

Reply

Marsh Posté le 08-09-2003 à 23:49:54    

j'etudie tout ca, merci  :jap:


---------------
-( BlackGoddess )-
Reply

Marsh Posté le 09-09-2003 à 15:13:22    

mon compilo (vc++7) me renvoit :
 
Erreur Foo
 
Foo()
~Foo()
Erreur Foo
 
Foo()
~Foo()
Erreur Foo
 
Foo()
~Foo()
***Erreur Foo
~Bar3()
~Foo()
~Foo()
~Foo()
 
je comprends pas trop d'ou viennent les 3 derniers ~Foo()...
 
pour le reste, d'apres ce que j'ai compris les objets construits avant l'exception sont détruits, ceux qui étaient en train de se construire (l'exception est remontée a travers leurs constructeurs) sont laissés en plan et pas détruit, et evidemment ceux qui auraient du être construit apres l'exception ne le sont pas.


---------------
-( BlackGoddess )-
Reply

Marsh Posté le 09-09-2003 à 19:15:07    

moi j'ai ça
 
 
Erreur Foo
 
Foo()
~Foo()
Erreur Foo
 
Foo()
~Foo()
Erreur Foo
 
Foo()
~Foo()
***Erreur Foo
Erreur Foo
 
 
c'est un problème parce que gcc fait une optimisation de base suggérer par la norme. fais un constructeur de copie avec un affichage et tu verras

Reply

Marsh Posté le 09-09-2003 à 19:33:40    

Citation :

encapsuler systématiquement les allocations dans des porteurs


 
c'est du chinois pour moi, qq1 peut m'expliquer ?
sinon j'essaie de me plonger dans la doc de la stl, mais ce n'est malheureusement pas à ma portée encore visiblement...


---------------
-( BlackGoddess )-
Reply

Marsh Posté le 09-09-2003 à 19:34:25    

merci Taz  :jap:  j'ai bien compris le principe des exceptions dans les constructeurs :)


---------------
-( BlackGoddess )-
Reply

Sujets relatifs:

Leave a Replay

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