OVH Cloud OVH Cloud

Exception multiples

114 réponses
Avatar
bernard tatin
J'ai un problème d'exceptions multiples qui, je pense, est bien décrit
par le code suivant :

// une exception
class Excp {
public:
Excp(char *msg) : message (msg) {}
virtual ~Excp() {}
inline string& getMessage () {
return message;
}
protected:
string message;
};

// une classe simple
class B {
public:
B(int j) : k(j) {}
inline void run () {
throw Excp("exception imprévue dans le run");
}
virtual ~B () { throw Excp("Bad B"); }
private:
int k;
};

void test_excp () {
try {
try {
B b(-5);
b.run();
std::cout << "Création de B ... et sortie" << std::endl;
}
catch (Excp &e) {
std::cout << "Exception " << e.getMessage() << std::endl;
}
}
catch (Excp &e) {
std::cout << "Exception " << e.getMessage() << std::endl;
}
catch (...) {
std::cout << "Exception inconnue" << std::endl;
}
}

int main () {
test_excp ();
return 0;
}

Je comprend que l'exception déclenchée dans b.run() provoque la sortie
du bloc et donc la destruction de l'objet b. Une nouvelle exception est
alors levée. Je pensais que mes try/catch résolverais le problème, mais
ce n'est pas le cas. J'ai un message
Executable “tests” has exited due to signal 6 (SIGABRT).
Et rien d'autre. C'est un vrai plantage. Si je supprime l'un des deux
throw, j'ai le résultat attendu.

J'utilise gcc 3.3 sur MacOS 10.3.5.

Est-ce que quelqu'un a des explications ? Je sais comment m'en dépétrer,
ce qui m'intéresse c'est le pourquoi du comment.

Merci.

Bernard.

10 réponses

1 2 3 4 5
Avatar
bernard tatin
Andre Heinen wrote:
Quant à la récursion infinie, je sais que c'est possible, mais je
n'en ai jamais vu. Je n'ai encore jamais vu de destructeur qui
appelle exit(). Et quand bien même ce serait le cas, encore
faudrait-il que ce soient justement des instances de cette
classe-là qui soient détruites par exit().



J'avais réussi à le faire il y a quelques années. Je n'ai plus le code.
Ce dont je suis sûr c'est qu'en supprimant exit d'un de mes
destructeurs, le problème a disparu.

Dans le cadre de mon petit projet, les exits sont donc maintenant au
nombre de 1 dans 1 destructeur, dans 1 classe qu'il est impossible
d'instancier plus d'une fois correctement - et qui va bientôt devenir un
singleton. Donc, pour l'instant, je ne cours pas trop de risques.

Bernard

Avatar
bernard tatin
Andre Heinen wrote:
En fait, ce n'est pas la mémoire qui me tracasse: elle sera de
toute façon libérée par le système d'exploitation. Je pense
plutôt à des fichiers à flusher. Ceci dit, comme Jean-Marc et
toi le faites remarquer, si on en arrive à une telle extrémité,
il y a des chances pour que le cleanup ne soit plus possible.



Mon problème c'est une fermeture correcte d'un ou plusieurs socket et de
quelques fichiers. L'exit est suffisament brutal pour que le serveur de
socket d'en face soit souvent obligé de ne réagir que sur un time-out.
Actuellement ce n'est pas très génant mais à terme, cela est ennuyeux.
Le serveur bloque des ressources inutilement pendant un temps assez long
(deux minutes). Je pense que je vais utiliser le couple exit/atexit et
une ou deux variables globales pour faire au plus propre.

Bernard

Avatar
Laurent Deniau
bernard tatin wrote:
Andre Heinen wrote:

En fait, ce n'est pas la mémoire qui me tracasse: elle sera de
toute façon libérée par le système d'exploitation. Je pense
plutôt à des fichiers à flusher. Ceci dit, comme Jean-Marc et
toi le faites remarquer, si on en arrive à une telle extrémité,
il y a des chances pour que le cleanup ne soit plus possible.



Mon problème c'est une fermeture correcte d'un ou plusieurs socket et de
quelques fichiers. L'exit est suffisament brutal pour que le serveur de
socket d'en face soit souvent obligé de ne réagir que sur un time-out.
Actuellement ce n'est pas très génant mais à terme, cela est ennuyeux.
Le serveur bloque des ressources inutilement pendant un temps assez long
(deux minutes). Je pense que je vais utiliser le couple exit/atexit et
une ou deux variables globales pour faire au plus propre.


une methode plus C++ consisterait a deleger a un objet statique la
liberation des ressources en cas de stack unwinding dans le destructeur.

a+, ld.


Avatar
Jean-Marc Bourguet
Andre Heinen writes:

On 27 Oct 2004 13:57:21 +0200, Jean-Marc Bourguet
wrote:

Ou via assert().


Attention, assert() fonctionnera dans le code de test mais pas dans
le code de production. Il ne faut pas l'utiliser pour gérer des
erreur susceptibles de se produire après la phase de debug.


Depuis quand on enleve les gilets de sauvetage quand on part en mer?

A+

--
Jean-Marc, neem mij niet kwalijk, Dijsktra
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org


Avatar
Jean-Marc Bourguet
Andre Heinen writes:

On 27 Oct 2004 14:01:30 +0200, Jean-Marc Bourguet
wrote:

Andre Heinen writes:

Si on appelle exit(), on court le risque d'appeler des destructeurs
qui peuvent eux-mêmes tenter d'arrêter le programme en appelant
exit(), d'où une récursion infinie.


Je n'aime pas exit() en C++, mais j'ai le souvenir que ca doit
fonctionner sans probleme.


Si tu n'as pas de récursion infinie, ça fonctionne sans problème,
mais sans appeler les destructeurs des objets automatiques.


Il me semblait que exit etait programme de sorte a ne jamais appele
deux fois une fonction enregistree avec atexit et donc j'espere un
destructeur. Mais je n'ai pas cherche de reference.

A+

--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org



Avatar
Jean-Marc Bourguet
bernard tatin writes:

Andre Heinen wrote:
En fait, ce n'est pas la mémoire qui me tracasse: elle sera de
toute façon libérée par le système d'exploitation. Je pense
plutôt à des fichiers à flusher. Ceci dit, comme Jean-Marc et
toi le faites remarquer, si on en arrive à une telle extrémité,
il y a des chances pour que le cleanup ne soit plus possible.



Mon problème c'est une fermeture correcte d'un ou plusieurs socket et de
quelques fichiers. L'exit est suffisament brutal pour que le serveur de
socket d'en face soit souvent obligé de ne réagir que sur un
time-out. Actuellement ce n'est pas très génant mais à terme, cela est
ennuyeux. Le serveur bloque des ressources inutilement pendant un temps
assez long (deux minutes). Je pense que je vais utiliser le couple
exit/atexit et une ou deux variables globales pour faire au plus propre.


Je te cite:

Lorsque le programme qui utilise ma classe est bien écrit, bien
testé et la classe utilisée correctement, l'exception ne devrait
jamais être levée.

Pourquoi le timeout deviendrait un probleme?

Mais s'il y a des choses que tu veux faire dans ce cas, une fonction
de cleanup speciale qui finit par abort me semble preferable a exit
qui appellera on ne sait pas quoi. Mais si tu te retrouve dans un
etat impossible, pourquoi est-ce que les donnees utilisees n'auraient
pas ete corrompue?

A+

--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org


Avatar
Luc Hermitte
bernard tatin wrote in news:SfIfd.9223
$:

Je pressentais bien qu'une excception dans un destructeur n'était pas
une bonne idée, mais je ne trouvais rien à ce sujet.


http://www.gotw.ca/gotw/


--
Luc Hermitte <hermitte at free.fr>
FAQ de <news:fr.comp.lang.c++> :
<http://www.cmla.ens-cachan.fr/Utilisateurs/dosreis/C++/FAQ/>
Dejanews : <http://groups.google.com/advanced_group_search>

Avatar
Andre Heinen
On 27 Oct 2004 15:22:37 +0200, Jean-Marc Bourguet
wrote:

Il me semblait que exit etait programme de sorte a ne jamais appele
deux fois une fonction enregistree avec atexit et donc j'espere un
destructeur. Mais je n'ai pas cherche de reference.


Je n'ai pas ma documentation sous la main, mais puisque Bernard
nous dit que ça lui est déjà arrivé, je suppose que ma mémoire ne
m'a pas trahi...

--
Andre Heinen
My address, rot13-encoded: n qbg urvara ng rhebcrnayvax qbg pbz

Avatar
Andre Heinen
On 27 Oct 2004 15:18:09 +0200, Jean-Marc Bourguet
wrote:

Depuis quand on enleve les gilets de sauvetage quand on part en mer?


Si tu refuses d'enlever ton gilet de sauvetage quand tu pars en
mer, il est d'autant plus important de ne jamais utiliser
assert(), puisqu'elle ne sera pas compilée dans les versions
release...

Personnellement il m'est arrivé de coder des assert() qui
ralentissaient considérablement le programme. Dans ce cas, c'est
un mécanisme pratique. Quand tu testes, tant pis si le programme
est plus lent: tu veux tout vérifier. A partir du moment où tu
as le sentiment de ne plus (trop) courir de risque, tu définis
NDEBUG, les assert() disparaissent, et le code devient
suffisamment rapide pour être mis en production.

--
Andre Heinen
My address, rot13-encoded: n qbg urvara ng rhebcrnayvax qbg pbz

Avatar
Jean-Marc Bourguet
Andre Heinen writes:

On 27 Oct 2004 15:18:09 +0200, Jean-Marc Bourguet
wrote:

Depuis quand on enleve les gilets de sauvetage quand on part en mer?


Si tu refuses d'enlever ton gilet de sauvetage quand tu pars en mer,
il est d'autant plus important de ne jamais utiliser assert(),
puisqu'elle ne sera pas compilée dans les versions release...


Je viens de verifier, le code que nous livrons n'est pas compile avec
-DNDEBUG et il me semblait que c'etait une pratique courante.

A+
--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org


1 2 3 4 5