Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

De l'usage des exceptions

106 réponses
Avatar
Guillaume Gourdin
Bonjour à tous,

selon ma (modeste) expérience, les exceptions en C++sont très largement sous
utilisées, et on en reste (me semble t-il) toujours à la bonne vieille
méthode du retour d'un code d'erreur. Je suis un peu surpris de cet état de
fait, les exceptions étant supposées apporter une gestion plus performantes
des erreurs. J'ai dons quelques questions: est-il vrai que les exceptions
sont sous utilisées? Quels sont vos retours d'expérience? Ou bien y a t'il
une raison plus profonde à la sous-utilisation des exceptions?

Merci!

- Guillaume -

10 réponses

Avatar
Patrick 'Zener' Brunet
Bonsoir.

"Michael Doubez" a écrit dans le message
de news
On 8 juil, 00:18, "Patrick 'Zener' Brunet"
wrote:
"Michael Doubez" a écrit dans le message
de news

On 5 juil, 11:41, "Patrick 'Zener' Brunet"
wrote:
"Guillaume Gourdin" a écrit dans le message
de news 4a4f3042$0$30992$









[...] big snip






A priori c'est-là la cause essentielle du divorce entre
l'informatique industrielle et celles "de gestion" et "avancée".
Il serait temps de les réconcillier... Je ne vois rien de malsain
dans une gestion de la mémoire en temps que ressource
comptabilisée plutôt que supposée "prévue suffisante".



C'est toujours une question de coûts. C'est moins cher d'acheter une
barette mémoire que de passer du temps sur du code.




Réponse moyenne.
On calcule et on gère, ou bien on majore au pif et on compte sur la
chance...




Ensuite, comment passe-t-on cette exception (que "throwe"-t-on) ?
Par adresse, référence ou par copie ?





Pour autant que je sache, on ne peux pas lancer par référence.
Un bonne règle est de lancer par valeur et de catcher par
référence pour éviter le slicing.



Oui, j'ai été confus... On lance par valeur et on propage/manipule
par référence ensuite.

Ben en fait je ne sais pas vraiment comment ça s'implémente à la
compilation: à quel moment se fait le démontage de la pile par
rapport au cycle de l'exception.



La pile est dépilée jusqu'au handler le plus proche qui match
l'exception et le controle lui est transféré.

Parce qu'elle est instanciée en sommet de pile, et le catch se
trouve bien plus profond... Si dans le bloc catch je déclare une
variable automatique, elle se met où sur la pile ?



L'endroit de l'allocation est /unspecified/ d'après le standard
(§15.1/4)

Elle est traitée de la même façon qu'une valeur retournée par
return.



Sauf que pour un return (d'une structure par exemple), a priori c'était
prévu et elle a été allouée sur la pile avant d'empiler les arguments de la
fonction (moi en tout cas j'implémenterais comme ça).

Pour une exception... Il faudrait faire ça avant la fonction parce qu'elle
est invoquée dans un bloc try et qu'il y a un catch associé pour ce type de
structure-exception ?

Bon, de toute manière on va se retrouver avec le même problème que pour
retourner un objet depuis un opérateur friend (la string dans l'opérateur +
concaténation par exemple). C'est le fameux contexte qui impose l'existence
d'un constructeur de copie. Donc il y a copie (2 copies en fait avec
l'instance fantôme)...
Et donc pour une string ou similaire: malloc, memcpy, free et encore malloc
etc.
Edifiant à suivre au debugger.

[...]



Exemple vécu (même pas besoin d'un missile, un trieur industriel):

La machine (1 hectare environ) est pilotée directement par des
racks OS/9 ou similaires, mais pour le contrôle de process on met
volontiers du PC (plusieurs rendondants éventuellement) parce que:
- c'est puissant pour pas cher,
- ça permet de faire des IHM évoluées que le client réclame,
- ça peut intégrer une DB Oracle ou Sybase,
- c'est moins impossible à interfacer avec du gros système COBOL
(côté compta),
- les développeurs qui connaissent se trouvent plus facilement sur
le marché,
- divers...

En fonctionnement normal, s'il y a un écran, il est dans une
armoire et personne ne le regarde, hors maintenance.
Quand bien même quelqu'un verrait la MessageBox "Erreur d'accès au
fichier TOTO.DAT", la plupart des opérateurs ne savent même pas ce
qu'est un fichier.



Un signal sonore/lumineux est toujours possible.



"l'informatique appelle au secours"

Et si le responsable de prod intervient, il va bien comprendre
"qu'il y a une .erde avec l'informatique", mais ensuite ?
Usine bloquée à 2h00 du mat, 500 opérateurs qui poireautent, les
camionneurs aussi, le réassort de toute la distribution de la
région pour le lendemain première heure qui est compromis...
Là le responsable réveille son PDG qui réveille celui de la SSII,
et vous imaginez la suite...

Donc à moins d'un tremblement de terre majeur, le process DOIT se
débrouiller tout seul :o)






Evidemment c'est très dûr à réussir, mais c'est quand même bien de
ne pas y renoncer d'emblée pour se faciliter le codage.
Alors on essaie de blinder au maximum et de récupérer à tout prix
tout problème qui peut l'être d'une manière quelconque.



Je suis d'accord. Ne serait ce que pour des coûts de maintenance et
de qualité de service mais si le pire du pire arrive, dans ce que
j'ai vu, ils se posent pas la question et redémarrent la machine.
Si ça ne marche pas, RAZ du système.




J'ai oublié ce détail:

Dans ce genre de bécane, les données de tri sont de gigantesques listes
chaînées très dynamiques, dépendantes du flux, donc à peu près impossibles à
reconstituer si on les perd.
La session de tri dure environ 5h, les camions partent au fur et à mesure et
les factures aussi. Il est donc hors de question de recommencer.
Or on a plus d'une dizaine de transactions par secondes, ce qui fait qu'on
ne peut pas faire des flush sur fichier en permanence.

Donc oui, on peut faire une RAZ du système, mais à condition de se
débrouiller pour qu'après reboot il puisse reprendre là où il en était, en
retrouvant son gros contexte de tri en mémoire. Les racks OS/9 assurent une
mise en queue des encours durant ces quelques minutes, ensuite ça rattrape.

Tout le problème fut de trouver une techno pour avoir cette grosse mémoire
dynamique mais résistante au crash.
(on a testé en tirant puis rebranchant la prise durant le tri à plein
régime)

Sur le drone sur lequel je travaillais, les processus étaient
monitoré et si les ressource système étaient épuisées, le système
redémarrait les services proprement.




S'il peut retrouver un contexte viable, bien sûr.

Si le système s'était corrompu, un failback relançait une RAZ du
système et si ça ne marchait pas non plus, l'utilisateur avait une
clé USB permettant de le faire à la mano (plug and boot) ... en
supposant qu'il ait pu atterrir en mode dégradé :)



Pour un drone militaire, il vaut peut-être mieux qu'il s'auto-détruise dans
ce cas, non ?

Bon, on est d'accord: l'impératif de robustesse dans certains domaines crée
des problèmes passionnants qui nous changent de l'applet bureautique, qui a
le droit de planter parce que "l'info n'est pas une science exacte", pas
vrai ?
;-)

--
Cordialement.

* Patrick BRUNET www.ipzb.fr www.ipzb-pro.com
* E-mail: lien sur http://zener131.eu/ContactMe
Avatar
James Kanze
On Jul 8, 7:11 pm, ld wrote:
On 8 juil, 10:25, James Kanze wrote:
> On Jul 7, 2:50 pm, ld wrote:



> > On 7 juil, 11:17, James Kanze wrote:
> > > Il n'a de signification pour le client qu'après l'échec
> > > d'une lecture (et c'est surtout une signification inversée
> > > -- s'il n'est pas positionné, alors que failbit l'est, c'est
> > > qu'il y a une erreur de format dans le fichier). La raison
> > > pourquoi il ne fait jamais de sens qu'il génère une
> > > exception, c'est précisement parce qu'il ne signifie rien
> > > pour le client, qu'il peut être positionné d'une façon un
> > > peu aléatoire, non selon ce qu'on vient de lire (ou qu'on
> > > vient d'essayer à lire), mais selon ce qui suit dans le
> > > fichier, et même la façon que istream fonctionne
> > > internellement.
> > ? Pas tout compris... Si on voit un eofbit, c'est que la fin
> > de fichier a ete _effectivement_ vue, pas seulement que l'on
> > s'y trouve.



> Pas au niveau du client. Essaie :



> int
> main()
> {
> std::istringstream s( "1.23" ) ; // pas de 'n' final !!!
> double d ;
> s >> d ;
> std::cout << s.eof() << std::endl ;
> return 0 ;
> }



> Après le « s >> d », le client n'a pas encore rencontré la fin ;



je ne sais pas ce que tu appelles le "client" dans ce code.
Mais il est clair que le stream a rencontre la fin, ce qui
entre dans le cadre de ce que je disais (c'etait suppose etre
un contre exemple?)



C-à-d que le stream doit lever une exception dans ce cas-ci ?

> il a bien lu son double. Mais normalement, le eofbit sera
> positionné.



oui et?



Et donc, on ne veut pas d'exception (qui l'empêcherait de
traiter le double).

> Indépendamment de l'utilisation de l'exception, oui, il faut
> bien incorporer des informations du parser dans le rapport de
> l'erreur. D'habitude, je fais quelque chose du genre :



> parser.error( severity ) << "invalid field value: " << value ;



> (Voire simplement « error( severity )... », si je suis dans une
> fonction du parseur, ce qui est généralement le cas.) Ensuite,
> le destructeur du temporaire renvoyé par la fonction error fait
> ce qu'il faut -- si on veut une exception, c'est là (eh oui,
> dans le destructeur) qu'on la lève.



je ne joue pas ce jeux la...



Et cependant, il fonctionne on ne peut plus bien. Il permet le
formattage de l'erreur directement où il le faut, sans exiger de
variable (ostringstream) supplémentaire. Le coup du temporaire
est utile pour d'autres choses aussi -- dans un environement
multi-threadé, par exemple, c'est lui qui gère le mutex.

--
James Kanze (GABI Software) email:
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Avatar
Michael Doubez
On 8 juil, 23:20, "Patrick 'Zener' Brunet"
wrote:
Bonsoir.

"Michael Doubez" a écrit dans le message
 de news com



> On 8 juil, 00:18, "Patrick 'Zener' Brunet"
> wrote:
>> "Michael Doubez" a écrit dans le message
>> de news
>>
>>> On 5 juil, 11:41, "Patrick 'Zener' Brunet"
>>> wrote:
>>>> "Guillaume Gourdin" a écrit dans le message
>>>> de news 4a4f3042$0$30992$
>> [...]    big snip
>> A priori c'est-là la cause essentielle du divorce entre
>> l'informatique industrielle et celles "de gestion" et "avancée".
>> Il serait temps de les réconcillier... Je ne vois rien de malsain
>> dans une gestion de la mémoire en temps que ressource
>> comptabilisée plutôt que supposée "prévue suffisante".

> C'est toujours une question de coûts. C'est moins cher d'acheter une
> barette mémoire que de passer du temps sur du code.

Réponse moyenne.
On calcule et on gère, ou bien on majore au pif et on compte sur la
chance...



Dans un projet, c'est très tentant de jouer sur la qualité pour
arriver au bout.

En fin de compte ça coute plus cher mais ça se voit moins.

>>>> Ensuite, comment passe-t-on cette exception (que "throwe"-t-on) ?
>>>> Par adresse, référence ou par copie ?

>>> Pour autant que je sache, on ne peux pas lancer par référence.
>>> Un bonne règle est de lancer par valeur et de catcher par
>>> référence pour éviter le slicing.

>> Oui, j'ai été confus... On lance par valeur et on propage/manipule
>> par référence ensuite.

>> Ben en fait je ne sais pas vraiment comment ça s'implémente à la
>> compilation: à quel moment se fait le démontage de la pile par
>> rapport au cycle de l'exception.

> La pile est dépilée jusqu'au handler le plus proche qui match
> l'exception et le controle lui est transféré.

>> Parce qu'elle est instanciée en sommet de pile, et le catch se
>> trouve bien plus profond... Si dans le bloc catch je déclare une
>> variable automatique, elle se met où sur la pile ?

> L'endroit de l'allocation est /unspecified/ d'après le standard
> (§15.1/4)

> Elle est traitée de la même façon qu'une valeur retournée par
> return.

Sauf que pour un return (d'une structure par exemple), a priori c'était
prévu et elle a été allouée sur la pile avant d'empiler les argum ents de la
fonction (moi en tout cas j'implémenterais comme ça).



D'après le standard, je n'ai pas l'impression qu'elle soit copiée
(copié de n2914 mais c'est +ou- le même):
§15.1/3
A throw-expression initializes a temporary object, called the
exception object[...]The temporary is an lvalue and is used to
initialize the variable named in the matching handler (15.3).[...]

§15.1/4
The memory for the temporary copy of the exception being thrown is
allocated in an unspecified way, except as noted in 3.7.4.1. The
temporary persists as long as there is a handler being executed for
that exception.[...]

Et §15.1/5
When the thrown object is a class object, the copy constructor and the
destructor shall be accessible, even if the copy operation is elided

Ca laisse penser que la seule copie possible est au moment du throw.


Pour une exception... Il faudrait faire ça avant la fonction parce qu'e lle
est invoquée dans un bloc try et qu'il y a un catch associé pour ce t ype de
structure-exception ?

Bon, de toute manière on va se retrouver avec le même problème que pour
retourner un objet depuis un opérateur friend (la string dans l'opéra teur +
concaténation par exemple). C'est le fameux contexte qui impose l'exist ence
d'un constructeur de copie. Donc il y a copie (2 copies en fait avec
l'instance fantôme)...
Et donc pour une string ou similaire: malloc, memcpy, free et encore mall oc
etc.
Edifiant à suivre au debugger.



> [...]
>> Exemple vécu (même pas besoin d'un missile, un trieur industriel):

>> La machine (1 hectare environ) est pilotée directement par des
>> racks OS/9 ou similaires, mais pour le contrôle de process on met
>> volontiers du PC (plusieurs rendondants éventuellement) parce que:
>> - c'est puissant pour pas cher,
>> - ça permet de faire des IHM évoluées que le client réclame,
>> - ça peut intégrer une DB Oracle ou Sybase,
>> - c'est moins impossible à interfacer avec du gros système COBOL
>> (côté compta),
>> - les développeurs qui connaissent se trouvent plus facilement sur
>> le marché,
>> - divers...

>> En fonctionnement normal, s'il y a un écran, il est dans une
>> armoire et personne ne le regarde, hors maintenance.
>> Quand bien même quelqu'un verrait la MessageBox "Erreur d'accès au
>> fichier TOTO.DAT", la plupart des opérateurs ne savent même pas ce
>> qu'est un fichier.

> Un signal sonore/lumineux est toujours possible.

"l'informatique appelle au secours"



L'informatique prévient que tu pourrait perdre quelques doigts.

Plus sérieusement, nous avions des signaux sonores sur certains
éléments critiques (énergie basse, pas de réponse d'un module ... ) .

[snip]
> Sur le drone sur lequel je travaillais, les processus étaient
> monitoré et si les ressource système étaient épuisées, le sys tème
> redémarrait les services proprement.

S'il peut retrouver un contexte viable, bien sûr.



J'avais une zone durcie pour le peu de contexte nécessaire.
C'est vrai que dans les autres cas ...

> Si le système s'était corrompu, un failback relançait une RAZ du
> système et si ça ne marchait pas non plus, l'utilisateur avait une
> clé USB permettant de le faire à la mano (plug and boot) ... en
> supposant qu'il ait pu atterrir en mode dégradé :)

Pour un drone militaire, il vaut peut-être mieux qu'il s'auto-détruis e dans
ce cas, non ?



C'est prévu. Ca donne lieu à des bugs comiques et des techniciens pas
contents de reccupérer une machine en kit.

Bon, on est d'accord: l'impératif de robustesse dans certains domaines crée
des problèmes passionnants qui nous changent de l'applet bureautique, q ui a
le droit de planter parce que "l'info n'est pas une science exacte", pas
vrai ?
;-)



Oui. C'est ce qui fait des journées excitantes.

--
Michael
Avatar
James Kanze
On Jul 9, 10:16 am, Michael Doubez wrote:
On 8 juil, 23:20, "Patrick 'Zener' Brunet"
wrote:



[...]
> >>>> Ensuite, comment passe-t-on cette exception (que
> >>>> "throwe"-t-on) ? Par adresse, référence ou par copie ?



> >>> Pour autant que je sache, on ne peux pas lancer par référence.
> >>> Un bonne règle est de lancer par valeur et de catcher par
> >>> référence pour éviter le slicing.



> >> Oui, j'ai été confus... On lance par valeur et on
> >> propage/manipule par référence ensuite.



> >> Ben en fait je ne sais pas vraiment comment ça
> >> s'implémente à la compilation: à quel moment se fait le
> >> démontage de la pile par rapport au cycle de l'exception.



> > La pile est dépilée jusqu'au handler le plus proche qui
> > match l'exception et le controle lui est transféré.



> >> Parce qu'elle est instanciée en sommet de pile, et le
> >> catch se trouve bien plus profond... Si dans le bloc
> >> catch je déclare une variable automatique, elle se met où
> >> sur la pile ?



> > L'endroit de l'allocation est /unspecified/ d'après le standard
> > (§15.1/4)



> > Elle est traitée de la même façon qu'une valeur retournée par
> > return.



> Sauf que pour un return (d'une structure par exemple), a
> priori c'était prévu et elle a été allouée sur la pile avant
> d'empiler les arguments de la fonction (moi en tout cas
> j'implémenterais comme ça).



C'est une technique courrante d'implémentation, mais la norme ne
le précise pas. La mémoire pour la valeur de retour est allouée
d'une façon qui dépend de l'implémentation, comme le mémoire
d'une exception.

D'après le standard, je n'ai pas l'impression qu'elle soit copiée
(copié de n2914 mais c'est +ou- le même):
§15.1/3
A throw-expression initializes a temporary object, called the
exception object[...]The temporary is an lvalue and is used to
initialize the variable named in the matching handler (15.3).[...]



Et comment se passe-t-il l'initialisation de l'objet temporaire,
sinon que par une copie ?

§15.1/4
The memory for the temporary copy of the exception being thrown is
allocated in an unspecified way, except as noted in 3.7.4.1. The
temporary persists as long as there is a handler being executed for
that exception.[...]



Et §15.1/5
When the thrown object is a class object, the copy constructor and the
destructor shall be accessible, even if the copy operation is elided



Ca laisse penser que la seule copie possible est au moment du throw.



Si tu catches par valeur, il y aurait une copie là aussi. La
declaration dans le catch crée bien une variable à lui, qui
serait initialisée avec l'objet temporaire. (Si tu catches par
référence, évidemment, l'initialisation d'une référence ne copie
pas.)

--
James Kanze (GABI Software) email:
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Avatar
Michael Doubez
On 10 juil, 09:53, James Kanze wrote:
On Jul 9, 10:16 am, Michael Doubez wrote:

> On 8 juil, 23:20, "Patrick 'Zener' Brunet"
> wrote:

    [...]



> > >>>> Ensuite, comment passe-t-on cette exception (que
> > >>>> "throwe"-t-on) ?  Par adresse, référence ou par copie ?
> > >>> Pour autant que je sache, on ne peux pas lancer par référence .
> > >>> Un bonne règle est de lancer par valeur et de catcher par
> > >>> référence pour éviter le slicing.
> > >> Oui, j'ai été confus... On lance par valeur et on
> > >> propage/manipule par référence ensuite.
> > >> Ben en fait je ne sais pas vraiment comment ça
> > >> s'implémente à la compilation: à quel moment se fait le
> > >> démontage de la pile par rapport au cycle de l'exception.
> > > La pile est dépilée jusqu'au handler le plus proche qui
> > > match l'exception et le controle lui est transféré.
> > >> Parce qu'elle est instanciée en sommet de pile, et le
> > >> catch se trouve bien plus profond... Si dans le bloc
> > >> catch je déclare une variable automatique, elle se met où
> > >> sur la pile ?
> > > L'endroit de l'allocation est /unspecified/ d'après le standard
> > > (§15.1/4)
> > > Elle est traitée de la même façon qu'une valeur retournée p ar
> > > return.
> > Sauf que pour un return (d'une structure par exemple), a
> > priori c'était prévu et elle a été allouée sur la pile avan t
> > d'empiler les arguments de la fonction (moi en tout cas
> > j'implémenterais comme ça).

C'est une technique courrante d'implémentation, mais la norme ne
le précise pas. La mémoire pour la valeur de retour est allouée
d'une façon qui dépend de l'implémentation, comme le mémoire
d'une exception.

> D'après le standard, je n'ai pas l'impression qu'elle soit copiée
>  (copié de n2914 mais c'est +ou- le même):
> §15.1/3
> A throw-expression initializes a temporary object, called the
> exception object[...]The temporary is an lvalue and is used to
> initialize the variable named in the matching handler (15.3).[...]

Et comment se passe-t-il l'initialisation de l'objet temporaire,
sinon que par une copie ?



C'est ce que j'avais dit plus bas, l'initialisation est le seul moment
ou elle est éventuellement copiée.
> Ca laisse penser que la seule copie possible est au moment du throw.



Et encore, le compilateur est autorisé à faire l'élision.
Ce que je voulais dire est qu'il n'y a pas de copie au moment du catch
(sauf catch par valeur).

> §15.1/4
> The memory for the temporary copy of the exception being thrown is
> allocated in an unspecified way, except as noted in 3.7.4.1. The
> temporary persists as long as there is a handler being executed for
> that exception.[...]
> Et §15.1/5
> When the thrown object is a class object, the copy constructor and the
> destructor shall be accessible, even if the copy operation is elided
> Ca laisse penser que la seule copie possible est au moment du throw.

Si tu catches par valeur, il y aurait une copie là aussi. La
declaration dans le catch crée bien une variable à lui, qui
serait initialisée avec l'objet temporaire. (Si tu catches par
référence, évidemment, l'initialisation d'une référence ne copi e
pas.)



Nous sommes d'accord mais nous parlions ici de la propagation de
l'"exception object" jusqu'au catch.
La question était: Est-il copié pour chaque dépilement au fur et à
mesure que nous remontons dans les fonctions ?

La réponse que je propose d'après le standard est non.
Mais ça parait magique. Où est it alloué dans les faits (disons sur
gcc) ?

--
Michael
Avatar
James Kanze
On Jul 10, 12:08 pm, Michael Doubez wrote:
On 10 juil, 09:53, James Kanze wrote:



Nous sommes d'accord mais nous parlions ici de la propagation
de l'"exception object" jusqu'au catch. La question était:
Est-il copié pour chaque dépilement au fur et à mesure que
nous remontons dans les fonctions ?



Certainement pas. (Évidemment, dans le cas où un programme
conformant ne peut pas distinguer, un compilateur peut le
faire.)

La réponse que je propose d'après le standard est non. Mais
ça parait magique. Où est it alloué dans les faits (disons sur
gcc) ?



Je ne connais pas le cas de g++, mais Sun CC alloue dans une
zone réservée (statiquement) de la mémoire. Et s'il ne reste
plus de la mémoire dans cette zone, c'est une épuisement des
ressources, donc, un comportement indéfini (en fait, il appel
abort). À vrai dire, je ne vois pas beaucoup d'autres solutions,
au moins pour std::bad_alloc. (Un alternatif serait d'appeler
new(nothrow), avec l'utilisation de la zone réservée qu'en cas
d'échec.)

--
James Kanze (GABI Software) email:
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Avatar
espie
In article <4a4f3042$0$30992$,
Guillaume Gourdin wrote:
Bonjour à tous,

selon ma (modeste) expérience, les exceptions en C++sont très largement sous
utilisées, et on en reste (me semble t-il) toujours à la bonne vieille
méthode du retour d'un code d'erreur. Je suis un peu surpris de cet état de
fait, les exceptions étant supposées apporter une gestion plus performantes
des erreurs. J'ai dons quelques questions: est-il vrai que les exceptions
sont sous utilisées? Quels sont vos retours d'expérience? Ou bien y a t'il
une raison plus profonde à la sous-utilisation des exceptions?



Apres avoir parcouru rapidement ce fil de discussion (une semaine de vacances),
je suis surpris de ne pas avoir vu de plus visibles references a Herb Sutter.
(ou alors, tout le monde l'inclut de facon implicite ?). Ses divers travaux
(gotw, exceptional C++ et ses suites) sont quand meme fortement centres sur
la difficulte de faire des choses correctes en presence d'exceptions...
ce que j'en ai retenu, c'est que si toute la chaine n'est pas super-propre
cote destructeurs, laisser des exceptions se propager n'est pas raisonnable
(deja, on a les destructeurs, et donc on echappe au cauchemar du finally de
java)

Apres, cote pratique, en tant que participant a l'equipe d'OpenBSD, j'ai
vu de tres pres les problemes d'adaptation de compilateur a un systeme,
et les exceptions sont vraiment un des aspects les plus complexes de tout
ceci. Entre les dependances a la toolchain (binutils) qui necessitent
d'avoir tout plus ou moins a jour, le calvaire de tout ce qui est dependant
de l'architecture dans ce bazar (la necessite de tester toute modif, meme
apparemment triviale, sur une dizaine d'architectures distinctes---oui, le
couple binutils/g++ n'est pas tres solide et d'un design tres douteux),
les interactions avec les bibliotheques partagees, les threads, les
exceptions posent des problemes de detail. Ca n'est pas complique: c'est
LE truc qui pete une fois sur deux quand on fait des modifs dans notre
toolchain.

Bref, ca n'est que depuis peu (a tout casser 5 ans) que les exceptions
fonctionnent en C++. Ca n'est que depuis encore moins qu'elles ont "enfin"
un cout negligeable et que la difference entre -fno-exceptios et -fexceptions
est descendue a <1% sur la grande majorite des systemes.

Pas tres surprenant qu'elles soient peu utilisees, surtout vu la difference
de mentalite cote programmation qu'elles impliquent (pour avoir des
exceptions, il faut vraiment faire du C++, et plus du C ameliore...)
Avatar
Fabien LE LEZ
On Mon, 13 Jul 2009 09:26:16 +0000 (UTC), (Marc
Espie):

Ses divers travaux
(gotw, exceptional C++ et ses suites) sont quand meme fortement centres sur
la difficulte de faire des choses correctes en presence d'exceptions...



Certes, mais c'est relativement indépendant de la question qui nous
occupe :

- Presque n'importe quel code peut lancer une exception, donc ton code
doit être exception-safe de toute façon, que tu lances toi-même des
exceptions ou pas.

- Sutter dit surtout que d'une manière générale, le code
exception-safe est meilleur / moins bancal.
Par exemple :
- RAII au lieu de s'amuser à libérer les ressources soi-même
- Idiome "swap" pour l'opérateur de copie, plutôt que bricoler
avec du "if (this != &rhs)".
Avatar
Fabien LE LEZ
On Mon, 13 Jul 2009 09:26:16 +0000 (UTC), (Marc
Espie):

(pour avoir des
exceptions, il faut vraiment faire du C++, et plus du C ameliore...)



Yep. C'est le gros problème du C++, et qui lui a donné si mauvaise
réputation : beaucoup de programmeurs, venant du C, continuent à
programmer en presque-C.
Avatar
espie
In article ,
Fabien LE LEZ wrote:
On Mon, 13 Jul 2009 09:26:16 +0000 (UTC), (Marc
Espie):

Ses divers travaux
(gotw, exceptional C++ et ses suites) sont quand meme fortement centres sur
la difficulte de faire des choses correctes en presence d'exceptions...





Certes, mais c'est relativement indépendant de la question qui nous
occupe :



- Presque n'importe quel code peut lancer une exception, donc ton code
doit être exception-safe de toute façon, que tu lances toi-même des
exceptions ou pas.



Non. Il y a des tonnes de projets que je connais qui preconisaient et
preconisent encore le -fno-exceptions. => ca veut dire qu'il y a plein de
projets qui interdisent explicitement dans leur cahier des charges la levee
d'exceptions... et qui sont codes en consequence.

Evidemment, ca n'est pas toujours marque, mais je me garderai bien d'utiliser
des exceptions avec du code que je n'ai pas ecrit si je n'ai pas quelques
paragraphes dans la documentation de ce code qui mentionnent explicitement
la gestion des exceptions.