j'ai quasiment aucun destructeur (je me
suis converti au RAII).
j'ai quasiment aucun destructeur (je me
suis converti au RAII).
j'ai quasiment aucun destructeur (je me
suis converti au RAII).
"Aurélien REGAT-BARREL" writes:
Pour cela je me suis dit que verify() pouvait renvoyer une
espèce de flux qui dans son destructeur déclenche une
exception (s'il le faut).
A priori, je dirais que si l'un des opérateurs << lance une
exception, le destructeur du flux sera appelé, et là, BOOM !
ÀMHA, lancer une exception dans un destructeur est extrêmement
délicat.
Il faut pouvoir assurer qu'aucune exception ne sera lancée
entre la création et la destruction de chacune des instances.
Ce qui doit pourvoir néanmoins être fait dans certains cas
particuliers. Dans ce cas-ci, il faudrait imposer que les
surcharges de l'opérateur << pour ce flux ne lancent pas
d'exceptions.
"Aurélien REGAT-BARREL" <nospam-aregatba@yahoo.fr.invalid> writes:
Pour cela je me suis dit que verify() pouvait renvoyer une
espèce de flux qui dans son destructeur déclenche une
exception (s'il le faut).
A priori, je dirais que si l'un des opérateurs << lance une
exception, le destructeur du flux sera appelé, et là, BOOM !
ÀMHA, lancer une exception dans un destructeur est extrêmement
délicat.
Il faut pouvoir assurer qu'aucune exception ne sera lancée
entre la création et la destruction de chacune des instances.
Ce qui doit pourvoir néanmoins être fait dans certains cas
particuliers. Dans ce cas-ci, il faudrait imposer que les
surcharges de l'opérateur << pour ce flux ne lancent pas
d'exceptions.
"Aurélien REGAT-BARREL" writes:
Pour cela je me suis dit que verify() pouvait renvoyer une
espèce de flux qui dans son destructeur déclenche une
exception (s'il le faut).
A priori, je dirais que si l'un des opérateurs << lance une
exception, le destructeur du flux sera appelé, et là, BOOM !
ÀMHA, lancer une exception dans un destructeur est extrêmement
délicat.
Il faut pouvoir assurer qu'aucune exception ne sera lancée
entre la création et la destruction de chacune des instances.
Ce qui doit pourvoir néanmoins être fait dans certains cas
particuliers. Dans ce cas-ci, il faudrait imposer que les
surcharges de l'opérateur << pour ce flux ne lancent pas
d'exceptions.
Pourquoi lever une exception au lieu de tout arreter si c'est
une assertion ?
Ben l'exception est un bon moyen de tout arrêter proprement
non ?
Je compte l'utiliser comme un assert() amélioré certes, mais
pas seulement, aussi voire surtout pour vérifier le code de
retour de fonctions systèmes / d'une bibliothèque tierce
(pilotage d'une caméra scientifique...). Si une telle fonction
échoue, je peux pas faire grand chose, mais pas la peine de
vautrer tout le logiciel. Cette exception sera catchée un peu
plus haut et transformée en OperationFailed, l'utilisateur
averti et puis c'est tout. Le log contiendra plus de détails
sur l'origine de l'échec (le message associé au verify()).
- Si tu utilises ton 'verify' a l'intérieur d'un destructeur,
il faudra prendre garde a rattraper l'exception dans le
destructeur pour ne pas risquer d'avoir une destruction
inachevée.
Peu de risques que cela se produise, j'ai quasiment aucun
destructeur (je me suis converti au RAII).
- Si tu inseres dans ton operator<< le résultat d'une fonction
qui leve une exception, tu auras une 2eme levée d'exception
non rattrapée lors de la destruction de la pile, ce qui est
justement le truc a éviter quand on dit de ne pas lever
d'exception dans un destructeur.
C'est effectivement une possibilité, genre:
verify( value != 0 ) << "La valeur de la classe " <<
this->getName() << " est nulle.";
si getName() lève une exception je suis mal...
Peu de risques malgré tout, bad_alloc me semble le principal.
Moyennant une bonne doc écrite en rouge clignotant, on devrait
pouvoir s'assurer de la chose.
Au niveau utilisation, vous en pensez quoi ? Je trouve ça bien
plus pratique que ce que j'ai fait jusque là:
if ( value >= 10 )
{
std::ostringstream oss;
oss << "La valeur n'est pas un chiffre : " << value;
throw std::logic_error( oss.str() );
}
Vous faîtes comment vous ?
Pourquoi lever une exception au lieu de tout arreter si c'est
une assertion ?
Ben l'exception est un bon moyen de tout arrêter proprement
non ?
Je compte l'utiliser comme un assert() amélioré certes, mais
pas seulement, aussi voire surtout pour vérifier le code de
retour de fonctions systèmes / d'une bibliothèque tierce
(pilotage d'une caméra scientifique...). Si une telle fonction
échoue, je peux pas faire grand chose, mais pas la peine de
vautrer tout le logiciel. Cette exception sera catchée un peu
plus haut et transformée en OperationFailed, l'utilisateur
averti et puis c'est tout. Le log contiendra plus de détails
sur l'origine de l'échec (le message associé au verify()).
- Si tu utilises ton 'verify' a l'intérieur d'un destructeur,
il faudra prendre garde a rattraper l'exception dans le
destructeur pour ne pas risquer d'avoir une destruction
inachevée.
Peu de risques que cela se produise, j'ai quasiment aucun
destructeur (je me suis converti au RAII).
- Si tu inseres dans ton operator<< le résultat d'une fonction
qui leve une exception, tu auras une 2eme levée d'exception
non rattrapée lors de la destruction de la pile, ce qui est
justement le truc a éviter quand on dit de ne pas lever
d'exception dans un destructeur.
C'est effectivement une possibilité, genre:
verify( value != 0 ) << "La valeur de la classe " <<
this->getName() << " est nulle.";
si getName() lève une exception je suis mal...
Peu de risques malgré tout, bad_alloc me semble le principal.
Moyennant une bonne doc écrite en rouge clignotant, on devrait
pouvoir s'assurer de la chose.
Au niveau utilisation, vous en pensez quoi ? Je trouve ça bien
plus pratique que ce que j'ai fait jusque là:
if ( value >= 10 )
{
std::ostringstream oss;
oss << "La valeur n'est pas un chiffre : " << value;
throw std::logic_error( oss.str() );
}
Vous faîtes comment vous ?
Pourquoi lever une exception au lieu de tout arreter si c'est
une assertion ?
Ben l'exception est un bon moyen de tout arrêter proprement
non ?
Je compte l'utiliser comme un assert() amélioré certes, mais
pas seulement, aussi voire surtout pour vérifier le code de
retour de fonctions systèmes / d'une bibliothèque tierce
(pilotage d'une caméra scientifique...). Si une telle fonction
échoue, je peux pas faire grand chose, mais pas la peine de
vautrer tout le logiciel. Cette exception sera catchée un peu
plus haut et transformée en OperationFailed, l'utilisateur
averti et puis c'est tout. Le log contiendra plus de détails
sur l'origine de l'échec (le message associé au verify()).
- Si tu utilises ton 'verify' a l'intérieur d'un destructeur,
il faudra prendre garde a rattraper l'exception dans le
destructeur pour ne pas risquer d'avoir une destruction
inachevée.
Peu de risques que cela se produise, j'ai quasiment aucun
destructeur (je me suis converti au RAII).
- Si tu inseres dans ton operator<< le résultat d'une fonction
qui leve une exception, tu auras une 2eme levée d'exception
non rattrapée lors de la destruction de la pile, ce qui est
justement le truc a éviter quand on dit de ne pas lever
d'exception dans un destructeur.
C'est effectivement une possibilité, genre:
verify( value != 0 ) << "La valeur de la classe " <<
this->getName() << " est nulle.";
si getName() lève une exception je suis mal...
Peu de risques malgré tout, bad_alloc me semble le principal.
Moyennant une bonne doc écrite en rouge clignotant, on devrait
pouvoir s'assurer de la chose.
Au niveau utilisation, vous en pensez quoi ? Je trouve ça bien
plus pratique que ce que j'ai fait jusque là:
if ( value >= 10 )
{
std::ostringstream oss;
oss << "La valeur n'est pas un chiffre : " << value;
throw std::logic_error( oss.str() );
}
Vous faîtes comment vous ?
Aurélien REGAT-BARREL wrote:
Pourquoi lever une exception au lieu de tout arreter si
c'est une assertion ?
Ben l'exception est un bon moyen de tout arrêter proprement
non ?
Ca se discute. Certains disent qu'en cas d'assert, tu n'es pas
certain de l'état dans lequel tu es, et donc il vaut mieux
arrêter tout au plus vite.
D'autres disent que même si le premier argument est vrai, si
le désagrément causé par un arrêt brutal est relativement
élevé, et si ce qui peut se passer au cas ou le programme
perdre totalement les pédales n'est pas dramatique, vu que la
probalité que ça se passe vraiment mal est assez faible
(estimation sans justification...), il vaut mieux lancer une
exception qui va arrêter calmement le programme.
J'avoue ne pas savoir me situer entre les deux camps.
Vous faîtes comment vous ?
Je ne fais pas, mais je me demande si un truc tordu comme le
suivant pourrait marcher :
class DoOnceAndThrow
{
DoOnceAndThrow() isAlreadyDone(false) {}
void tryToDoIt()
{
if (isAlreadyDone)
throw std::exception;
isAlreadyDone = true;
}
bool isAlreadyDone;
}
#define verify(b)
DoOnceAndThrow doat##__LINE__; // 1
if (b) ; // 2
else
while(doOnceAndThrow())
log
// 1 : Pour essayer de ne pas avoir deux identificateurs
portant le même nom dans la même portée. Ne marchera que s'il
n'y a pas 2 verifie sur une seule ligne
// 2 : Permet d'éviter des trucs étranges si verifie est appelé dans un
if qui comporte un else, par exemple.
Aurélien REGAT-BARREL wrote:
Pourquoi lever une exception au lieu de tout arreter si
c'est une assertion ?
Ben l'exception est un bon moyen de tout arrêter proprement
non ?
Ca se discute. Certains disent qu'en cas d'assert, tu n'es pas
certain de l'état dans lequel tu es, et donc il vaut mieux
arrêter tout au plus vite.
D'autres disent que même si le premier argument est vrai, si
le désagrément causé par un arrêt brutal est relativement
élevé, et si ce qui peut se passer au cas ou le programme
perdre totalement les pédales n'est pas dramatique, vu que la
probalité que ça se passe vraiment mal est assez faible
(estimation sans justification...), il vaut mieux lancer une
exception qui va arrêter calmement le programme.
J'avoue ne pas savoir me situer entre les deux camps.
Vous faîtes comment vous ?
Je ne fais pas, mais je me demande si un truc tordu comme le
suivant pourrait marcher :
class DoOnceAndThrow
{
DoOnceAndThrow() isAlreadyDone(false) {}
void tryToDoIt()
{
if (isAlreadyDone)
throw std::exception;
isAlreadyDone = true;
}
bool isAlreadyDone;
}
#define verify(b)
DoOnceAndThrow doat##__LINE__; // 1
if (b) ; // 2
else
while(doOnceAndThrow())
log
// 1 : Pour essayer de ne pas avoir deux identificateurs
portant le même nom dans la même portée. Ne marchera que s'il
n'y a pas 2 verifie sur une seule ligne
// 2 : Permet d'éviter des trucs étranges si verifie est appelé dans un
if qui comporte un else, par exemple.
Aurélien REGAT-BARREL wrote:
Pourquoi lever une exception au lieu de tout arreter si
c'est une assertion ?
Ben l'exception est un bon moyen de tout arrêter proprement
non ?
Ca se discute. Certains disent qu'en cas d'assert, tu n'es pas
certain de l'état dans lequel tu es, et donc il vaut mieux
arrêter tout au plus vite.
D'autres disent que même si le premier argument est vrai, si
le désagrément causé par un arrêt brutal est relativement
élevé, et si ce qui peut se passer au cas ou le programme
perdre totalement les pédales n'est pas dramatique, vu que la
probalité que ça se passe vraiment mal est assez faible
(estimation sans justification...), il vaut mieux lancer une
exception qui va arrêter calmement le programme.
J'avoue ne pas savoir me situer entre les deux camps.
Vous faîtes comment vous ?
Je ne fais pas, mais je me demande si un truc tordu comme le
suivant pourrait marcher :
class DoOnceAndThrow
{
DoOnceAndThrow() isAlreadyDone(false) {}
void tryToDoIt()
{
if (isAlreadyDone)
throw std::exception;
isAlreadyDone = true;
}
bool isAlreadyDone;
}
#define verify(b)
DoOnceAndThrow doat##__LINE__; // 1
if (b) ; // 2
else
while(doOnceAndThrow())
log
// 1 : Pour essayer de ne pas avoir deux identificateurs
portant le même nom dans la même portée. Ne marchera que s'il
n'y a pas 2 verifie sur une seule ligne
// 2 : Permet d'éviter des trucs étranges si verifie est appelé dans un
if qui comporte un else, par exemple.
Et ça doit faire quoi, exactement ? Je ne comprends rien du code
dans le macro.
Et évidemment, ton if/else ne sert à rien ici. Parce que si
j'écris :
if ( a > b )
verify( c > b ) << ... ;
il n'y aurait que la declaration de doat##__LINE__ qui se trouve
dans l'if ; le if/else est une deuxième instruction. (Et si
j'ajoute un else à mon if, ci-dessus, ça ne compile même pas.
Et ça doit faire quoi, exactement ? Je ne comprends rien du code
dans le macro.
Et évidemment, ton if/else ne sert à rien ici. Parce que si
j'écris :
if ( a > b )
verify( c > b ) << ... ;
il n'y aurait que la declaration de doat##__LINE__ qui se trouve
dans l'if ; le if/else est une deuxième instruction. (Et si
j'ajoute un else à mon if, ci-dessus, ça ne compile même pas.
Et ça doit faire quoi, exactement ? Je ne comprends rien du code
dans le macro.
Et évidemment, ton if/else ne sert à rien ici. Parce que si
j'écris :
if ( a > b )
verify( c > b ) << ... ;
il n'y aurait que la declaration de doat##__LINE__ qui se trouve
dans l'if ; le if/else est une deuxième instruction. (Et si
j'ajoute un else à mon if, ci-dessus, ça ne compile même pas.
Aurélien REGAT-BARREL wrote:Pourquoi lever une exception au lieu de tout arreter si c'est
une assertion ?
Ben l'exception est un bon moyen de tout arrêter proprement
non ?
Proprement, c'est rélatif. L'exception ne peut pas créer la
propreté une fois que c'est partie. En fait, il y a une risque
que les destructeurs l'empire. En fait, quand rien ne va comme
on s'y attendait, un core dump reste ce qu'il y a de plus
propre. Au moins on est sûr de ne pas faire plus de dégats qu'on
n'en a déjà fait.
Peu de risques que cela se produise, j'ai quasiment aucun
destructeur (je me suis converti au RAII).
? RAII, c'est de tout faire dans les destructeurs, plutôt que
dans une logique externe.
Aurélien REGAT-BARREL wrote:
Pourquoi lever une exception au lieu de tout arreter si c'est
une assertion ?
Ben l'exception est un bon moyen de tout arrêter proprement
non ?
Proprement, c'est rélatif. L'exception ne peut pas créer la
propreté une fois que c'est partie. En fait, il y a une risque
que les destructeurs l'empire. En fait, quand rien ne va comme
on s'y attendait, un core dump reste ce qu'il y a de plus
propre. Au moins on est sûr de ne pas faire plus de dégats qu'on
n'en a déjà fait.
Peu de risques que cela se produise, j'ai quasiment aucun
destructeur (je me suis converti au RAII).
? RAII, c'est de tout faire dans les destructeurs, plutôt que
dans une logique externe.
Aurélien REGAT-BARREL wrote:Pourquoi lever une exception au lieu de tout arreter si c'est
une assertion ?
Ben l'exception est un bon moyen de tout arrêter proprement
non ?
Proprement, c'est rélatif. L'exception ne peut pas créer la
propreté une fois que c'est partie. En fait, il y a une risque
que les destructeurs l'empire. En fait, quand rien ne va comme
on s'y attendait, un core dump reste ce qu'il y a de plus
propre. Au moins on est sûr de ne pas faire plus de dégats qu'on
n'en a déjà fait.
Peu de risques que cela se produise, j'ai quasiment aucun
destructeur (je me suis converti au RAII).
? RAII, c'est de tout faire dans les destructeurs, plutôt que
dans une logique externe.
C'est peut-être pour cela que j'ai l'impression que l'utilité des
exceptions est en fait très limitée :
- soit on est dans un cas où rien ne va plus (risque de corruption, ...)
et alors autant sortir immédiatement
- soit on est dans un cas où il y a erreur, mais cette erreur n'a rien
"d'exceptionnel", au sens où elle est prévue par le workflow et, là je
préfère avoir mon propre système pour gérer les cas de fonctionnement
"dégradés" : ils sont souvent gérés localement et le mécanisme de remontée
d'exception n'apporte rien.
C'est peut-être pour cela que j'ai l'impression que l'utilité des
exceptions est en fait très limitée :
- soit on est dans un cas où rien ne va plus (risque de corruption, ...)
et alors autant sortir immédiatement
- soit on est dans un cas où il y a erreur, mais cette erreur n'a rien
"d'exceptionnel", au sens où elle est prévue par le workflow et, là je
préfère avoir mon propre système pour gérer les cas de fonctionnement
"dégradés" : ils sont souvent gérés localement et le mécanisme de remontée
d'exception n'apporte rien.
C'est peut-être pour cela que j'ai l'impression que l'utilité des
exceptions est en fait très limitée :
- soit on est dans un cas où rien ne va plus (risque de corruption, ...)
et alors autant sortir immédiatement
- soit on est dans un cas où il y a erreur, mais cette erreur n'a rien
"d'exceptionnel", au sens où elle est prévue par le workflow et, là je
préfère avoir mon propre système pour gérer les cas de fonctionnement
"dégradés" : ils sont souvent gérés localement et le mécanisme de remontée
d'exception n'apporte rien.
À tout hazard, dans ce cas-ci, je crois que j'emploierais mon
OutputStreamWrapper, modifié de façon à trapper et à ignorer
toute exception (ce qui a aussi l'avantage qu'aucune formattage
n'a lieu s'il n'y a pas de sortie.
Mais encore plus, je me poserais des questions sur l'utilisation
des exceptions dans ce cas-ci.
À tout hazard, dans ce cas-ci, je crois que j'emploierais mon
OutputStreamWrapper, modifié de façon à trapper et à ignorer
toute exception (ce qui a aussi l'avantage qu'aucune formattage
n'a lieu s'il n'y a pas de sortie.
Mais encore plus, je me poserais des questions sur l'utilisation
des exceptions dans ce cas-ci.
À tout hazard, dans ce cas-ci, je crois que j'emploierais mon
OutputStreamWrapper, modifié de façon à trapper et à ignorer
toute exception (ce qui a aussi l'avantage qu'aucune formattage
n'a lieu s'il n'y a pas de sortie.
Mais encore plus, je me poserais des questions sur l'utilisation
des exceptions dans ce cas-ci.
"Olivier Azeau" a écrit dans le message de news:
lbcGd.13468$C'est peut-être pour cela que j'ai l'impression que l'utilité des
exceptions est en fait très limitée :
- soit on est dans un cas où rien ne va plus (risque de corruption, ...)
et alors autant sortir immédiatement
- soit on est dans un cas où il y a erreur, mais cette erreur n'a rien
"d'exceptionnel", au sens où elle est prévue par le workflow et, là je
préfère avoir mon propre système pour gérer les cas de fonctionnement
"dégradés" : ils sont souvent gérés localement et le mécanisme de remontée
d'exception n'apporte rien.
Là où le mécanisme des exception me semble approprié, c'est lorsqu'on n'a
pas la réponse sur le comment traiter l'erreur (ou la circonstance
"exceptionnelle") à l'endroit où elle est repérée.
"Olivier Azeau" <john@doe.com> a écrit dans le message de news:
lbcGd.13468$Of5.9688@nntpserver.swip.net...
C'est peut-être pour cela que j'ai l'impression que l'utilité des
exceptions est en fait très limitée :
- soit on est dans un cas où rien ne va plus (risque de corruption, ...)
et alors autant sortir immédiatement
- soit on est dans un cas où il y a erreur, mais cette erreur n'a rien
"d'exceptionnel", au sens où elle est prévue par le workflow et, là je
préfère avoir mon propre système pour gérer les cas de fonctionnement
"dégradés" : ils sont souvent gérés localement et le mécanisme de remontée
d'exception n'apporte rien.
Là où le mécanisme des exception me semble approprié, c'est lorsqu'on n'a
pas la réponse sur le comment traiter l'erreur (ou la circonstance
"exceptionnelle") à l'endroit où elle est repérée.
"Olivier Azeau" a écrit dans le message de news:
lbcGd.13468$C'est peut-être pour cela que j'ai l'impression que l'utilité des
exceptions est en fait très limitée :
- soit on est dans un cas où rien ne va plus (risque de corruption, ...)
et alors autant sortir immédiatement
- soit on est dans un cas où il y a erreur, mais cette erreur n'a rien
"d'exceptionnel", au sens où elle est prévue par le workflow et, là je
préfère avoir mon propre système pour gérer les cas de fonctionnement
"dégradés" : ils sont souvent gérés localement et le mécanisme de remontée
d'exception n'apporte rien.
Là où le mécanisme des exception me semble approprié, c'est lorsqu'on n'a
pas la réponse sur le comment traiter l'erreur (ou la circonstance
"exceptionnelle") à l'endroit où elle est repérée.
En fin de compte, j'ai l'impression que la levée d'exception sert surtout
dans le cas d'un problème important qui impacte tout une "grosse"
sous-partie du programme, l'exception permettant alors de détruire
entièrement cette sous-partie et de redonner la main à un niveau élevé qui
va la reconstruire de zéro.
En fin de compte, j'ai l'impression que la levée d'exception sert surtout
dans le cas d'un problème important qui impacte tout une "grosse"
sous-partie du programme, l'exception permettant alors de détruire
entièrement cette sous-partie et de redonner la main à un niveau élevé qui
va la reconstruire de zéro.
En fin de compte, j'ai l'impression que la levée d'exception sert surtout
dans le cas d'un problème important qui impacte tout une "grosse"
sous-partie du programme, l'exception permettant alors de détruire
entièrement cette sous-partie et de redonner la main à un niveau élevé qui
va la reconstruire de zéro.