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

Avatar
Marc Boyer
In article , Andre Heinen wrote:
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...


Ca, c'est un choix du fournisseur du binaire.

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.


Ca, ça montre surtout que assert est trop simpliste pour un
contexte professionnel.
Heureusement, c'est une macro :-)

Marc Boyer
--
Je ne respecte plus le code de la route à vélo depuis une double fracture
due au fait que j'étais le seul à le respecter.


Avatar
Andre Heinen
On 27 Oct 2004 13:57:49 GMT, Marc Boyer
wrote:

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...


Ca, c'est un choix du fournisseur du binaire.


Certes. Mais je préfère ne pas courir le risque. Si un test est
suffisamment important pour que je veuille être sûr qu'il ne
disparaisse pas, je n'utilise pas assert().

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.


Ca, ça montre surtout que assert est trop simpliste pour un
contexte professionnel.


Pourquoi?

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


Avatar
Marc Boyer
Andre Heinen wrote:
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.


Ca, ça montre surtout que assert est trop simpliste pour un
contexte professionnel.


Pourquoi?


Pour moi, une macro chargée de vérifier des invariants devrait
1) donner plus d'info que le simple couple __LINE__ / __FILE__
par défaut (__fun__ aussi, puis un numéro de version)

2) permette d'activer/désactiver de manière plus fine
les invariant (notion de groupe et d'identité), permettre
des choses du genre
gcc -DNO_PRECOND(foo)
pour virer les preconditions de la fonction foo
gcc -DNO_GROUP_PRECOND(overflow)
pour virer globalement les tests d'overflow

3) le fait de simplement écrire dans stderr n'est pas
forcément ce qu'on attend, on peut vouloir un peu
plus, non ?

Ce genre de choses, non ?

Marc Boyer
--
Je ne respecte plus le code de la route à vélo depuis une double fracture
due au fait que j'étais le seul à le respecter.



Avatar
Fabien LE LEZ
On Wed, 27 Oct 2004 15:10:53 +0200, bernard tatin
:

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.


D'un autre côté, c'est sensé n'arriver qu'exceptionnellement, dans des
cas où il n'est même pas sûr que l'OS soit encore dans un état assez
stable pour fermer une connexion TCP.


--
;-)

Avatar
Andre Heinen
On 27 Oct 2004 14:28:41 GMT, Marc Boyer
wrote:

Pour moi, une macro chargée de vérifier des invariants devrait
1) ...
2) ...
3) ...

Ce genre de choses, non ?


Oui, en effet.

Pour ce que nous voulons vérifier dans les versions release,
nous utilisons des mécanismes plus efficaces qu'assert(). Mais
en plus, je mets parfois des assert() pour faire des
vérifications supplémentaires lors de mes premiers tests. Comme
c'est moi qui les exécute, assert() suffit.

C'est juste une bouée de plus. Je n'ai pas l'impression qu'elle
gêne.

Ceci dit, tout ceci me paraît confirmer ce que je disais tout à
l'heure, à savoir qu'il ne faut pas utiliser assert() pour des
problèmes susceptibles de se produire après que le code soit mis
en production.

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

Avatar
Christophe Lephay
Jean-Marc Bourguet wrote:
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?


Je crois que ça le gène plus pour les ressources consommées inutilement coté
serveur (donc en dehors de son programme)...

Chris

Avatar
bernard tatin
Christophe Lephay wrote:
Jean-Marc Bourguet wrote:

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?



Je crois que ça le gène plus pour les ressources consommées inutilement coté
serveur (donc en dehors de son programme)...

Chris




C'est exactement cela.

Bernard.


Avatar
Marc Boyer
In article , Andre Heinen wrote:
On 27 Oct 2004 14:28:41 GMT, Marc Boyer
wrote:
Pour ce que nous voulons vérifier dans les versions release,
nous utilisons des mécanismes plus efficaces qu'assert(). Mais
en plus, je mets parfois des assert() pour faire des
vérifications supplémentaires lors de mes premiers tests. Comme
c'est moi qui les exécute, assert() suffit.

C'est juste une bouée de plus. Je n'ai pas l'impression qu'elle
gêne.


Disons que à la question "est-ce qu'on enlève le gilet de
sauvetage pour aller en mer ?", la réponse est "oui, pour
en mettre un avec balise GPS".

Ceci dit, tout ceci me paraît confirmer ce que je disais tout à
l'heure, à savoir qu'il ne faut pas utiliser assert() pour des
problèmes susceptibles de se produire après que le code soit mis
en production.


C'est pour cela que je disais "heureusement qu'assert est une
macro", on peut alors faire
-Dassert(X)=production_assert(X)

Marc Boyer
--
Je ne respecte plus le code de la route à vélo depuis une double fracture
due au fait que j'étais le seul à le respecter.

Avatar
bernard tatin
Fabien LE LEZ wrote:
On Wed, 27 Oct 2004 15:10:53 +0200, bernard tatin
:


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.



D'un autre côté, c'est sensé n'arriver qu'exceptionnellement, dans des
cas où il n'est même pas sûr que l'OS soit encore dans un état assez
stable pour fermer une connexion TCP.


C'est censé n'arriver qu'exceptionnellement ... Je me méfie quand même.

Depuis tout à l'heure, je viens de trouver deux autres configurations
qui me mettent dans cette situation. Ce sont des actions extérieures qui
peuvent les provoquer. La manipulaion des sockets est assez complexe et
rattraper toutes les erreurs possibles est moins simple que je le croyais.

Bernard.


Avatar
Jean-Marc Bourguet
bernard tatin writes:

Christophe Lephay wrote:
Jean-Marc Bourguet wrote:

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?
Je crois que ça le gène plus pour les ressources consommées inutilement

coté serveur (donc en dehors de son programme)...
Chris


C'est exactement cela.


Un timeout de 2 minutes sur le serveur de temps en temps pendant la
periode de developpement (puisque ca ne devrait jamais arriver) pose
probleme? C'est quoi votre structure?

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