écrire en fin de ligne avec ofstream - C++ - Programmation
Marsh Posté le 12-06-2009 à 13:45:45
using namespace std;
ofstream fichier("tonfic", ios::out | ios::app);
fichier << "blabla" << endl;
On n'oublie pas de fermer après les écritures avec fichier.close();
Marsh Posté le 13-06-2009 à 09:27:24
pas besoin de close. ofstream est fermé lorsque l'instance de l'objet es detruite.
Rappel Ressource Allocation Is Initialisation
Marsh Posté le 13-06-2009 à 12:54:07
1/ std::ios::app ne permet pas d'écrire à la fin des lignes, uniquement à la fin du fichier. Le seul moyen que je connais est de recopier tout en ajoutant ce qu'on veut.
2/ Si close n'est pas nécessaire pour un fichier ouvert en lecture, en écriture le faire explicitement est le seul moyen de vérifier que tout est bien écrit. Ce qui peut ne pas être le cas sans que le programme ait un problème (voir http://groups.google.com/group/com [...] 202210f909 pour une anecdote sur ce qui est possible quand on ne vérifie pas ça).
Marsh Posté le 13-06-2009 à 13:20:06
ReplyMarsh Posté le 13-06-2009 à 15:57:17
Joel F a écrit : Ouasi, touchage de pipi là. |
Tu as déjà dû partir à l'étranger le lundi en étant averti le vendredi parce qu'un gros client a des données corrompues? Moi oui. Pas réellement ce que j'appelle du touchage de pipi même si certains commentaires entendus étaient plutôt scatologiques. Ce n'était pas un close qui dont le résultat n'était pas contrôlé, mais j'imagine très bien que ce soit possible.
Citation : Tu fais des local block et zou ... |
Est-ce que tu peux préciser? je ne vois pas comment faire -- à moins que tu ne parles d'utiliser basic_ios::exception(), mais son usage ne correspond pas à la pratique que j'ai constatée (je me demande si les seuls cas où je l'ai vu employé ne sont pas des exemples artificiels dans un cadre d'enseignement).
Marsh Posté le 14-06-2009 à 07:18:08
Code :
|
Marsh Posté le 14-06-2009 à 07:34:42
Je sais ce que sont des blocks, ma question est comment s'en servir pour détecter une erreur lors de l'exécution du destructeur sans utiliser des exceptions (qui introduisent entre autres problèmes un risque de double exception).
Marsh Posté le 14-06-2009 à 08:38:31
Non je n'est pas décris ce que sont les blocs mais j'ai voulu montrer ce qu'est un bloc local.
Marsh Posté le 14-06-2009 à 08:46:57
Si les exceptions posaient un problème, c'est qu'elles sont mal utilisées, s'il y a un risque de double exception, et bien il suffit d'imbriquer un TRY/CATCH dans le bloc CATCH.
Ce mécanisme (les exception) reste le meilleur en performance mais aussi pour la conception de modèles orientés objets. Ils ont l'avantage d'éclaircir le code, et d'alléger les diagrammes de transition et les organigrammes. Un machine à état ou un workflow en es simplifié aussi.
Si le travail est propre et rigoureux, les exceptions enlève plus de problèmes et n'en crée aucun, en tout cas je n'en ai jamais eu. C'est pour cela que ADA a d'ailleurs conservé sont mécanisme d'exception et que javascript en a crée un. A ma connaissance aucun langage n'a retiré son mécanisme d'extension, c'est plutot l'inverse. Il en de même pour le C++, au fil du temps C++ n'a pas supprimé son mécanisme d'extension. Et puis, si éviter de l'enlever est pour des raisons de compatibilité, c'est que justement beaucoup ont fait le choix de l'utiliser. La majorité aurait-elle tord? On serait tenté de répondre oui.
Marsh Posté le 14-06-2009 à 10:44:33
Corebreaker a écrit : Si les exceptions posaient un problème, c'est qu'elles sont mal utilisées, s'il y a un risque de double exception, et bien il suffit d'imbriquer un TRY/CATCH dans le bloc CATCH. |
Je n'ai rien à ajouter
Marsh Posté le 14-06-2009 à 18:30:59
Corebreaker a écrit : Si les exceptions posaient un problème, c'est qu'elles sont mal utilisées |
Nous sommes d'accord: utiliser les exceptions pour reporter un problème dans un destructeur est très souvent une mauvaise utilisation des exceptions.
Citation : s'il y a un risque de double exception, et bien il suffit d'imbriquer un TRY/CATCH dans le bloc CATCH. |
Il y a un risque de double exceptions dès qu'un destructeur peut jeter une exception. Si ta solution à ce risque consiste à mettre dans un try catch chaque déclaration d'une telle variable, ça ne me semble être une solution valable que quand on ne contrôle pas la classe dont le destructeur se comporte ainsi. Écrire des classes qui n'ont pas un tel constructeur me semble plus facile à utiliser et plus clair.
Citation : Ce mécanisme (les exception) reste le meilleur en performance mais aussi pour la conception de modèles orientés objets. |
Je connais une série de mécanismes de gestion d'erreur. Chacun d'eux me semble être adéquat dans certaines circonstances. Qualifier l'un deux de meilleur sans restriction me semble manquer de perspective.
Citation : Ils ont l'avantage d'éclaircir le code, et d'alléger les diagrammes de transition et les organigrammes. Un machine à état ou un workflow en es simplifié aussi. |
J'ai beaucoup de mal à accepter les affirmations générales dans ce genre là. Et celle-ci ne correspond pas à mon expérience. Il y a des cas où ne pas utiliser une exception mais un autre mécanisme rend le code plus clair.
Citation : Si le travail est propre et rigoureux, les exceptions enlève plus de problèmes et n'en crée aucun, en tout cas je n'en ai jamais eu. C'est pour cela que ADA a d'ailleurs conservé sont mécanisme d'exception et que javascript en a crée un. A ma connaissance aucun langage n'a retiré son mécanisme d'extension, c'est plutot l'inverse. Il en de même pour le C++, au fil du temps C++ n'a pas supprimé son mécanisme d'extension. Et puis, si éviter de l'enlever est pour des raisons de compatibilité, c'est que justement beaucoup ont fait le choix de l'utiliser. La majorité aurait-elle tord? On serait tenté de répondre oui. |
Je ne suis pas contre les exceptions en général: c'est un mécanisme qui rend effectivement bien des services s'il est employé à bon escient. Jeter une exception à partir d'un destructeur fait partie des cas où ce ne me semble pas être le cas.
Un autre cas où les exceptions me semblent être moins bonne qu'une alternative est quand une interface est définie comme jetant une exception quand le traitement en cas d'erreur doit généralement être fait par l'appelant immédiat. Exemple typique: les procédures open d'Ada (95, j'ai arrêté de faire de l'Ada sérieusement vers 2000 et n'ai pas suivi les évolutions introduites par Ada05). Une interface utilisant des codes d'erreur conduit à un code plus clair (idéalement, il faut un code d'erreur non ignorable, mais pour avoir utilisé les deux, dans ce cas je préfère le risque d'un code d'erreur ignorable à une utilisation d'exceptions. En passant un code d'erreur non ignorable est un cas où je trouve que jeter une exception à partir d'un destructeur est un choix défendable).
Marsh Posté le 14-06-2009 à 18:42:55
bon j'ai un truc comme ça qui traine au labo, je posterais ca en rentrant de WE
Marsh Posté le 14-06-2009 à 18:55:31
Un Programmeur a écrit :
|
Ça m'a rappelé une citation que je tente de mettre en signature car elle correspond bien à mon opinion sur les questions de conception et d'autres (Elle n'apparaît pas dans l'aperçu -- ce qui me gène -- et n'a pas eu d'effet rétroactif comme dans certains autres logiciels de forums -- ce que je trouve bien)
Edit: OK, elle est bien là.
Marsh Posté le 14-06-2009 à 22:45:55
Bon ok, je vois comment tu programmes.
Je suis désolé mais moi qui est fait beaucoup d'assembleur et de C et aussi du C sous windows (et même en pascal sous windows ou non), quand je me suis mis à la modélisation objet, j'ai vu que les exceptions étaient vraiment la solution à tous les problèmes de gestion des erreurs. Même les processeurs et dérivés ont appliqués très vite cette solution avec les tables d'interrutions (bien qu'au départ elles n'étaient pas sécurisé et on permis le développement de virus, maintenant tout va bien heureusement) qui sont en fait proche des exceptions au sens java / C++.
dans ces programmations de "bas niveau" j'ai longtemps été confronté à des codes genre:
Code :
|
Bon c'est un exemple simple, il y a des cas plus complexe, mais c'est l'esprit.
Parlons pas des noms des fonctions c'est pas le sujet. Ce que je veux faire remarquer est l'amoncèlement de if( appel() == ERREUR ) traitement_erreur(); qui devient très peu ragoutant à lire surtout pour du code Windows. Pour la lisibilité, peut mieux faire, d'ailleurs ça libèrerai ma tête de bien grosse migrainnes. Et aussi, normalement on doit propager un code d'erreur pour l'appelant de ce bout de code. Ca rajoute souvent tout plein d'instruction return ou affectation d'un code d'erreur, code d'erreur qui doivent peut-etre etre testés avec controles plus bas. Bref c'est sans fin, et ça fais de plus en plus mal à la tète, ah des fois ça donne envie de vomir (ça m'est arrivé une fois en plein boulot et sur le clavier en plus, ça a quand même fait un peut marrer les collègues mais pas le chef car le clavier était foutu). Donc, il y a des fois où cela s'étalait sur plus de 2000 lignes et finissaient par ressembler à des usines à gaz. De ce point vue, programmer pour un micro-contrôleur était plus plaisant que programmer pour de PC.
Si tu pense que ce genre de programmation est plus agréable et plus maintenable, c'est que t'as du faire affaire à des petites applications genre des trucs de 50000 lignes.
En modélisation, rentrer ce genre de trucs dans les diagrammes (avec une police normale évidemment, voire réduite pour certains car ils ne rentrait pas sur le A3 sinon), les fait exploser de telle manière qu'ils peuvent servir de papier peint (je ne mens pas c'est du vécu, on ne pouvez plus les utiliser sur nos propres bureaux).
Pour finir, mais désolé en full objet comme java, le concept d'exception faisant partie intégrante de la modélisation, le tout exception est possible. Et autre chose, j'ai migré une application vers du tout exception, eh bien il y a eu un gain en performance d'à peu près 20% avec tous les "if" que j'ai enlevé, ça me parait normal moi. Et au final, depuis que je les connais en C++, je n'ai vraiment eu l'occasion de faire un contrôle d'erreur avec des if, switch ou équivalent. Sauf bien sûr si comme dans le standard avec les flux, on est contraint de test les bits ios (ou ios_base maintenant).
Des fois c'est vrai qu'une exception peut servir à signaler quelque chose et aussi peut permettre par exemple à sortie d'une boucle (donc une utilisation similaire de setjmp/longmp en C/C++). C'est une pratique peu ortodoxe, mais si elle est correctement utilisée peut servir à rendre quelques service.
Citation : J'ai beaucoup de mal à accepter les affirmations générales dans ce genre là. Et celle-ci ne correspond pas à mon expérience. |
C'est simplement que je rapporte ma propre expérience, mais il est clair que cela tiens à chacun de me croire ou non.
Et puis ce n'est pas une affirmation générale, je ne vois pas où est le "général". Si par exemple dire "une expression de nombres non premiers avec les seuls 4 opérateurs de base est toujours réductible" est une affirmation générale alors oui la mienne en est une. Car elle est le constat de ma propre expérience. Donne moi un exemple qui semble contredire mon affirmation, je suis sûr de trouver une solution.
Citation : Il y a des cas où ne pas utiliser une exception mais un autre mécanisme rend le code plus clair. |
Pour ma part, je n'ai jamais observé d'une dégradation de la lisibilité en passant aux exception, au contraire, j'y ai toujours vu une amélioration. D'ailleurs j'ai du mal à comprendre comme l'utilisation d'exception peut dégrader la lisibilité. Puisque, le mécanisme:
- factorise du code.
- cache la gestion des erreurs qui peut justement embrouiller le lecteur.
- de plus, le mécanisme permet aussi un principe de boite noire ou de plugin car la gestion elle-même est décentralisée; ça peux faciliter une internationalisation de l'appli.
Il faudrait donc que me donne un exemple pour voir.
Citation : e ne suis pas contre les exceptions en général: c'est un mécanisme qui rend effectivement bien des services s'il est employé à bon escient. |
Justement le problème n'est pas de l'utiliser à bon escient, il est plutôt de l'utiliser correctement et pour ce dont il est fait. Car certains dérive son utilisation et vois dans les exceptions une solution miracle à certains problèmes, ils les utilisent un peut comme un "goto" par exemple. Mais en ce qui concerne la gestion des erreurs les exceptions peuvent s'utiliser partout. Si tu trouve un endroit où c'est impossible (tout en suivant les principes de la POO), alors donne le moi, je te montrerai comment y utiliser les exceptions de manière efficace.
Je rappelle autre chose pour les autres lecteurs, car je pense qu'on l'oublie trop souvent.
La grande force des exceptions est le principe de propagation; ça permet de filtrer les exceptions et ainsi définir des gestionnaires aux bons endroits. Ca permet aussi de "blackboxiser" ou "pluginiser" un gestionnaire très simplement (excusez l'anglicisme vaseux). Si vous voulez un exemple, je pourrais le fournir et monter la puissance de genre d'utilisation.
Propagation d'une exception:
Code :
|
Marsh Posté le 15-06-2009 à 10:53:54
Corebreaker a écrit : Bon ok, je vois comment tu programmes. |
Je réfléchis au problème que je cherche à résoudre, je pense en particulier au problème des évolutions problables, j'ignore les évolutions improbables et celles qui de toute façon demanderont une réanalyse de tout le contexte, j'examine ma boîte à outils de technique et je prends la plus adaptée. J'ai assez d'expérience pour savoir à quel point Brooks avait raison en affirmant there is no silver bullet et je sais quand utiliser you don't need it yet et quand ne pas le faire.
Citation : Je suis désolé mais moi qui est fait beaucoup d'assembleur et de C et aussi du C sous windows (et même en pascal sous windows ou non), |
J'ai également fait beaucoup d'assembleur (pour plusieurs processeurs) et de C aussi (et du Pascal, et de l'Ada, et du Lisp. Ça ce sont les langages que j'ai utilisé professionnellement en plus du C++, je ne vais pas citer tous les autres). Pas beaucoup sous Windows, mais sous Dos, Unix et quelques autres systèmes plus ou moins exotiques ou carrément sans système du tout.
Citation : quand je me suis mis à la modélisation objet, j'ai vu que les exceptions étaient vraiment la solution à tous les problèmes de gestion des erreurs. |
Certainement pas dans les destructeurs où ils posent plus de problèmes qu'ils n'en résolvent. Ce n'est pas par hasard que les conteneurs de la SL demandent que les types utilisés aient un destructeur qui ne jettent pas d'exception et que dans les discussions concernant un attribut nothrow, celui-ci serait implicite pour les destructeurs.
Certainement pas quand l'endroit normal où le traitement de l'erreur est l'endroit qui appelle la fonction d'interface jetant l'exception.
Les exceptions sont un excellent mécanisme quand l'erreur est à traiter loin de l'endroit où elle est découverte. Parfois à l'intérieur d'un module, où elles ne sont d'un détail d'implémentation de celui-ci et ne s'en échapperont pas, aux interfaces entre modules et alors le traitement du problème sera vraisemblablement fort générique et même pas dans le module appelant directement (ce sera au niveau de main() où on se contente de reporter un problème, au niveau d'une boucle d'interaction où on reporte le problème et on annulle l'opération en cours, à un niveau où on fait du rollback-retry pour implémenter un système transactionnel pour donner trois cas fréquents qui sont tout compte fait très semblable).
Citation : Même les processeurs et dérivés ont appliqués très vite cette solution avec les tables d'interrutions (bien qu'au départ elles n'étaient pas sécurisé et on permis le développement de virus, maintenant tout va bien heureusement) qui sont en fait proche des exceptions au sens java / C++. |
Je ne connais pas assez Java pour commenter sur ce langage. Mais les interruptions des processeurs date d'avant les exceptions dans les langages (fin des années 40 si j'ai bonne mémoire pour les interuptions, PL/I au milieu des années 60 pour les exceptions si je ne me trompe pas) et ont une série de caractéristiques qui en font des choses différentes des exceptions en C++. Elles peuvent être asynchrones, ce que les exceptions en C++ ne sont pas (avec cette caractéristique, le mécanisme du C++ le plus proche, c'est les signaux hérités du C) et après l'exécution du code associé, on continue généralement le flux d'instruction à l'endroit interrompu (à nouveau plus proche des signaux), ou bien on utilise quelque chose de plus proche de longjmp() que des exceptions.
Citation : dans ces programmations de "bas niveau" j'ai longtemps été confronté à des codes genre:
|
Si l'alternative à
Code :
|
est
Code :
|
je sais ce que je préfère. Les exceptions sont bien dans le cas suivant:
Code :
|
où oui on gagne en clareté à utiliser des exceptions
Citation : ...Et aussi, normalement on doit propager un code d'erreur pour l'appelant de ce bout de code... |
Qu'est-ce que je disais? Il ne faut pas chercher à me convaincre que les exceptions sont un mécanisme utile -- je le suis depuis longtemps -- mais que c'est toujours le meilleur.
Citation : Si tu pense que ce genre de programmation est plus agréable et plus maintenable, c'est que t'as du faire affaire à des petites applications genre des trucs de 50000 lignes. |
J'ai bien envie de te retourner le compliment: si tu penses qu'il y a des silver bullets et que les exceptions en sont une, c'est que ton expérience n'est pas assez variée. (En passant, 50000 c'est à peu près le nombre de fichiers de l'appli sur laquelle je travaille pour le moment).
Citation : Pour finir, mais désolé en full objet comme java, le concept d'exception faisant partie intégrante de la modélisation, le tout exception est possible. Et autre chose, j'ai migré une application vers du tout exception, eh bien il y a eu un gain en performance d'à peu près 20% avec tous les "if" que j'ai enlevé, ça me parait normal moi. Et au final, depuis que je les connais en C++, je n'ai vraiment eu l'occasion de faire un contrôle d'erreur avec des if, switch ou équivalent. Sauf bien sûr si comme dans le standard avec les flux, on est contraint de test les bits ios (ou ios_base maintenant). |
std::basic_ios::exception()
Citation :
|
Si
Citation : Ce mécanisme (les exception) reste le meilleur en performance mais aussi pour la conception de modèles orientés objets. |
et
Citation : quand je me suis mis à la modélisation objet, j'ai vu que les exceptions étaient vraiment la solution à tous les problèmes de gestion des erreurs. |
ne sont pas des affirmations générales je ne m'y connais pas. C'est volontairement que j'use et j'abuse de qualiticatif "généralement", "dans la plupart des cas", "le plus souvent",... quand je parle de conception parce que je ne me sens pas lié à une méthodologie de conception donnée -- fut-elle "full objet" -- et que ma pratique de la programmation est que je dois faire des compromis entre des contraintes contradictoires (et je suis heureux quand ces contraintes ne sont que techniques).
Citation :
|
Ce qui a lancé cette discussion:
Code :
|
ou l'allusion que j'ai faite à la lib d'Ada:
Code :
|
et tu me donnes une version qui utilise les exceptions pour signaler l'échec de open ou du constructeur. (Et tu remarqueras que j'ai aussi employé des exceptions, je continue à penser qu'elles sont souvent utiles, simplement pas à utiliser dans tous les cas).
Citation : Propagation d'une exception:
|
J'adore. Pas du tout. L'idée de jeter le résultat d'un new montre qu'on n'a pas compris quelque chose aux exceptions du C++ (ou du moins fréquenté trop longtemps d'autres langages et oublié les différences qu'il y a avec le C++).
Marsh Posté le 15-06-2009 à 12:23:09
Déjà dit mille fois: pour relancer une exception, il faut utiliser "throw;" sans arguments, sinon "throw e;" lance une nouvelle exception tronquée au type statique de "e".
Et sur votre touchage de nouilles, y a qu'a wrapper une bonne fois pour toute la gestion du code d'erreur avec des exceptions, comme ça par la suite, un unique et universel
Code :
|
est possible
là où la génaiel technique sur switch/if géant nécessite d'écrire un pavé ad-hoc à chaque fois.
Marsh Posté le 15-06-2009 à 14:05:00
Taz a écrit : y a qu'a |
Même demandes qu'aux autres:
- arrêter de prendre comme exemple des cas tellement abstraits qu'il nest pas possible de savoir si les exceptions sont une bonne solution ou pas et les cas où tout le monde est déjà convaincu que les exceptions sont la solution;
- montrer comment les exceptions clarifient les exemples que j'ai donnés. En particulier ce qui a déclenché ma participation dans cette discussion: l'utilisation d'une exception jetée dans le destructeur (i.e. ne pas avoir de close explicite mais utiliser le fait que le destructeur de ofstream ferme le fichier). Même s'il faut changer l'interface des IOStreams. J'ai jamais prétendu que la SL était parfaite même si je pense que dans la majorité des cas ses imperfections sont plus que compensées par le fait qu'elle soit standard; et la technique pourrait m'être utile dans le futur.
Marsh Posté le 15-06-2009 à 16:08:29
Bon c'est ici mon dernier message, et après je vous laisse dans votre délire. Là j'ai un petit raz-le-bol quand visiblement on cherche superficiellement à comprendre ce que je dis. On en est arriver à une discussion inutile car ça ressemble de plus en plus à dialogue de sourds. Vous pourrez rajouter d'autes bétises sans que ce coup ci je cherche à riposter (en effet, il est inutile d'essayer de creuser dans le béton avec une simple pelle). Ainsi les autres lecteurs vous donneront raison et vous pourrez vous complaire à avoir le dernier mot. Moi j'en ai marre d'essayer de chasser la fumée d'un volcan.
Car moi ce que je vois c'est que vous 2 (Taz et un programmeur) n'avez rien compris à ce que j'ai écris, sans doute un manque de clarté de ma part. Car j'ai l'impression que vous lisez et retenez les parties qui vous plaisent sans comprendre le texte dans sont intégralité. La preuve certaine de mes phrases sont sorties de son contexte pour argumenter des choses parfois inutiles ou hors sujet. (la preuve ci-dessous)
Un Programmeur a écrit : |
Quelle culture! Genre personne à part toi n'a jamais confronté à ces situations. Et ô dieu tu nous apporte la bonne manière de faire. Mais moi je ne vois pas ce que ça apporte au débat. On en n'est pas à utiliser des bloc fonctionnels, ou faire de l'analyse.
Un Programmeur a écrit :
|
Hors contexte. Tout le monde se fout de savoir ce que nous connaissons. On est pas là pour lister les langages qu'on connais, ou même faire un combat de celui qui connais le plus de chose, ce site à priori ne sert pas à cela.
Ce que tu as extrait et donc sortit de son contexte, n'était là que pour introduire ce qu'il avait après la virgule (as-tu lu ce qu'il y avait après la virgule? Car c'est ce qui importe vraiment).
Un Programmeur a écrit :
|
Autre preuve que tu n'a pas lu mon texte.
Un Programmeur a écrit : |
Nimporte quoi. Cette utilisation est réductrice. Le mécanisme des exceptions est bien plus puissant que cela. Suite à une affirmation pareille, quelque chose me dis que tu n'as pas totalement appréhendé tout le mécanisme, et donc que en a une vision superficielle.
Un Programmeur a écrit :
|
Là encore, cela prouve que tu n'as pas bien lu mon texte ou alors compris le tiers. Déjà je parlais des interrutions logicielles qui ne sont pas asynchrone. C'est vrai je ne l'ai pas mi explicitement, mais si tu avais lu tout le texte, tu aurais pu le déduire. Et puis, c'est juste ça mon argument:
Un Programmeur a écrit : Mais les interruptions des processeurs date d'avant les exceptions dans les langages |
En fait, là tu me paraphrase.
Citation : dans ces programmations de "bas niveau" j'ai longtemps été confronté à des codes genre:
|
Autre preuve que tu n'as pas lu mon texte. J'ai dis par la suite que justement il y avait des cas plus complexe. Tu me paraphrase encore.
(Me paraphraser, je suis désolé, mais il n'y a pas preuve plus tangible que tu ne lis pas ce que j'écris)
Un Programmeur a écrit :
|
Non, non, et non; tu n'as rien compris du tout !!!!
De plus, les premières version de la classe ios et des flux, n'utilisaient pas les exceptions.
J'essaie de dire, que si on utilise un bibliothèque n'utilise pas les exceptions pour la gestion d'erreur alors tu n'as pas le choix, d'où le "sauf" à la fin de la citation.
Un Programmeur a écrit :
|
Bah moi aussi. Mais je ne vois pas le rapport avec ce que j'ai dis (à part pour le "affirmation générale" ). Cela sonne comme de l'auto-justification.
En reprenant, lors d'une modélisation, si la problématique de gestion d'erreur, apparait, alors je pose un bloc fonctionnel intégrant le mécanisme d'exception. Mais le mécanisme en lui-même ne serait au final pas utilisé de la même manière suivant les interractions dans le modèle. Ca bien fait partie d'une boite à outils. Et ces outils permettent souvent de simplifier ou d'éclaircir une problématique. C'est dans ce sens qu'il fallait comprendre mes affirmations "générales".
Pour moi, ce n'est pas une affirmation générale, car le terme de généricité (donc l'adjectif "générale" ) s'appliquerait pour tous les outils employés et tous les langages utilisés. Or mes affirmations que tu qualifiais de "générales" ne s'appliquent pas aux langages n'ayant pas de mécanisme d'exception.
Un Programmeur a écrit :
|
Là encore, du hors contexte. Et tu n'a rien compris encore une fois. Si j'ai posté ceci:
Code :
|
C'est pour montrer un des aspect du mécanisme des exception, le principe de propagation qui peut servir ici pour filtrer des exceptions.
Explication du mot "filtrer": intercepter certaines exceptions et en laisser passer d'autres pour être traiter ailleurs.
Si tu relis plus attentivement, le précédent message tu le verras, en plus j'avais fait l'effort d'avoir mis un titre souligné.
c'est un EXEMPLE, juste un exemple, pas une version de quelque chose !!! C'est écris, lis donc !!! Et pendant qu'on y est lis aussi pourquoi j'ai cet exemple, et si te demande le rapport entre cet exemple et la discussion alors, relis attentivement, et réfléchis, tout est dans le texte, il suffit de lire.
Un Programmeur a écrit : J'adore. Pas du tout. L'idée de jeter le résultat d'un new montre qu'on n'a pas compris quelque chose aux exceptions du C++ (ou du moins fréquenté trop longtemps d'autres langages et oublié les différences qu'il y a avec le C++). |
Justement si tu avais pris conscience que ce n'étais qu'un exemple pour illustrer le filtrage, tu aurais compris justement la raison de ce qui te semble inadéquat. Et donc justement ce que tu crois montrer soit disant mon incompréhension, n'a pas de justification, ça ne montre rien du tout. Je pense en conséquence, mais ça tiens qu'à moi, mais jusque là plein de preuves et justifications apparaissant ici montre ma pensée, que j'ai mieux conscience que toi, de ce que sont les exceptions. Jeter un new ici a son utilité. J'aurais pu aussi faire throw Mon_Exception(e); à la ligne 24. Mais j'utilise le new même en C++ et pas seulement en java, car en C++, cela permet en effet de conserver l'instance de l'exception quelque part, mais ça me permet aussi de résoudre certains problèmes que vous avez déjà dû rencontrer aussi.
Pour conclure, je dirais juste qu'un tel manque de sérieux me fait demander si je vais continuer a évoluer sur ce site, d'autres comme codes-sources.com, sont un peu plus fiable je pense. Enfin là messieurs vous m'avez dégouté de ce site. Bref merci, pour l'instant je préfère me réfugier vers des valeurs sures. Je pensais pourtant passer un bon moment ici, mais je ne trouve que stress et migraines face à la connerie humaine.
Adieu.
Marsh Posté le 17-06-2009 à 10:40:27
ReplyMarsh Posté le 17-06-2009 à 12:22:26
Je vais résumer les points en faveur des quels j'ai essayé d'argumenter pour essayer d'éviter une dérive vers une position que je ne défends pas et de s'éloigner encore plus de la demande initiale.
1/ Il faut appeler close() explicitement dans le cas des ofstream pour être capable de gérer les erreurs qui peuvent avoir lieu pendant cette opération. Je citais comme raison le problème d'une double exception, mais après vérification, elle ne peut pas avoir lieu: le destructeur de ofstream ne jette pas d'exception même si une erreur a lieu pendant le close du rdbuf: il n'appelle pas setstate() dans ce cas (il n'appelle pas
ofstream::close() mais laisse agir le close implicite du filebuf). La situation est donc qu'il n'y a pas moyen de savoir qu'une erreur a eu lieu même si on active les exceptions.
2/ Bien que les exceptions soient un mécanisme utile, il y a des cas où elles ne sont pas le bon moyen de reporter une erreur. J'en citais deux:
a/ quand l'erreur aurait lieu pendant un destructeur. Il y a un risque de double exception et donc d'appel à std::terminate(). Il vaut mieux fournir un membre qui est capable de la reporter. Quand une erreur est détectée dans un destructeur, il est mieux l'ignorer (tout en maintenant les invariants, en passant c'est ce que fait ofstream) que jeter une exception. (Logger le problème est encore meilleur, utiliser un callback ou tout autre mécanisme plus souple est éventuellement aussi envisageable)
b/ quand une erreur reportée par une fonction d'interface d'un module est normalement traitée par l'appelant direct de la fonction plutôt que propagée. Je donnais le membre open des fstream en exemple.
A part la note
Citation : 2 It is usually inadvisable to throw an exception from a destructor in C++, since the destructor may itself be called during the stack-unwinding caused by another exception. If the second exception is |
qui conforte mon point 2a, je ne vois pas le rapport avec la discussion en cours. Ce papier argumente pour que les templates se comportent raisonnablement quand ils sont instanciés avec des types qui peuvent jeter des exceptions pendant certaines opérations. Il ne traite pas du problème de savoir quand les exceptions sont adaptées et quand elles ne le sont pas.
Marsh Posté le 17-06-2009 à 13:41:22
Un Programmeur a écrit : |
Je pense que, ca vient surtout du fait que la STL sur ce coup là nous pond un beau "faites ce que je dit pas ce que j e fait"
cf point plus loin
Un Programmeur a écrit : |
On ne devrait JAMAIS thrower dans un destructeur. les classes qui le font sont juste un peu bancales (stream en fait partie)
Un Programmeur a écrit : |
Je voulais ne quoter que ce point mais j'ai pas trouver le lien de l'ancre Désolé pour le bruit
Marsh Posté le 17-06-2009 à 15:20:16
Joel F a écrit : |
Je ne vois pas très bien comment faire autrement sur ce point:
- Elle fournit un membre pour fermer le fichier en permettant de détecter les erreurs (et qui va jeter une exception si on les a activées). C'est ainsi que le fichier sera fermé dans le flux d'exécution normal.
- Elle purge les tampons et ferme le fichier dans le destructeur sans générer d'exception, qu'on les ait activées ou non. Ça sert quand le fichier est fermé suite à une exception et qu'on désire le garder. Ttout ce qu'on aurait pu vouloir, c'est que quand c'est le destructeur qui ferme le fichier, on ait la possibilité de l'effacer automatiquement, ce qui me semble être le comportement désiré dans la majorité des cas quand on programme de manière robuste. Ça peut mériter un wrapper RAII.
Joel F a écrit : Je voulais ne quoter que ce point mais j'ai pas trouver le lien de l'ancre Désolé pour le bruit |
Ce n'est pas du bruit, c'était juste un peu trop succin pour connaître ton intention.
Marsh Posté le 17-06-2009 à 15:23:05
Joel F a écrit : |
Je comprends même pas qu'on ait une discussion à ce sujet: sauf changement de handler de std::terminate, autant appeler std::abort directement.
Marsh Posté le 17-06-2009 à 15:36:17
Un Programmeur a écrit : |
je le redit std::fstream est juste bancal. boost::iostreams a un meilleru comportement pr le coup
Un Programmeur a écrit : |
Non j'étais persuade d'avoir copier juste le bon lien :E
Marsh Posté le 17-06-2009 à 16:10:17
Joel F a écrit : |
Tu peux être plus explicite sur les différences que tu juges importantes? Je viens de parcourir la doc rapidement mais n'ai rien vu de pertinent à la discussion; le point qui nous intéresse -- le comportement en cas d'erreur détectée pendant le destructeur -- ne me semble pas différent (d'autres choses sont bien, je suis d'accord).
Marsh Posté le 17-06-2009 à 16:30:36
je faisais juste une supposition, je pense que leur destructeur sont tous no throw()
Marsh Posté le 18-05-2009 à 09:35:59
Bonjour, je souhaite écrire à la fin de chaque ligne d'un fichier existant avec ofstream.
Je ne vois pas trop comment faire. Des suggestions?
Cordialement,