IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C++ Discussion :

à propos de "l'idiome GetLastError"


Sujet :

C++

  1. #21
    Expert éminent

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Points : 6 911
    Points
    6 911
    Par défaut
    Citation Envoyé par r0d Voir le message
    . simplification de l'interface: les fonctions susceptibles de générer des erreurs ne renvoient qu'un simple booleen.
    Et si elles ont un autre résultat naturel?

    . avec cette technique, pas besoin de remonter les exceptions.
    Non, il faut a la place tester et copier explicitement...

    En passant c'est un mécanisme donnant un complément d'information sur une erreur, pas un mécanisme de signalement d'erreur.

    . simplification d'utilisation de la classe : l'utilisateur de cette classe ne s'occupe des erreurs que s'il en a besoin.
    En pratique il y a plus de problèmes graves dus aux erreurs non traitées quand il le faudrait que de gêne due au traitement obligatoire mais inutiles des erreurs.

    Citation Envoyé par JolyLoic Voir le message
    Je ne voir pas tant les exceptions comme un système de report d'erreur que comme un système de transport d'erreur.
    +1

    Citation Envoyé par bruno_pages Voir le message
    Je n'aime pas les exceptions, comme leur nom l'indique finalement elle ne devraient être utilisées qu'exceptionnellement .
    C'est le chemin d'exécution passant par elles qui en général ne doit être pris qu'exceptionnellement. Ce qui est normalement le cas pour la gestion des erreurs.

    Les exceptions sont avant tout un mécanisme de contrôle du flux d'exécution, comme l'appel de fonction, return, if, switch, goto,... en fait c'est un goto non local avec le label destination qui est déterminé par l'imbrication dynamique des appels. Ce n'est qu'accessoirement que c'est aussi un mécanisme de transport d'information.

    Étant un mécanisme par essence non local, il est bien adapté au traitement des erreurs qui sinon a tendance à encombrer le flux normal d'exécution, au point que parfois il ne soit plus visible. Mais cela ne veut pas dire que ce soit le seul mécanisme adapté pour transferer le point d'exécution en cas d'erreur.

    Comme il faut appeler les destructeurs sur les instances placées en pile lors de la descente liée à une levée d'exception le code produit pas le compilateur est beaucoup plus grand que sans (option de compilation).
    J'ai des doutes sur le fait que les alternatives conduisent un code généré plus compact.
    Les MP ne sont pas là pour les questions techniques, les forums sont là pour ça.

  2. #22
    Modérateur
    Avatar de bruno_pages
    Homme Profil pro
    ingénieur informaticien à la retraite
    Inscrit en
    Juin 2005
    Messages
    3 533
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 64
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : ingénieur informaticien à la retraite
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Juin 2005
    Messages : 3 533
    Points : 6 709
    Points
    6 709
    Par défaut
    Citation Envoyé par Jean-Marc.Bourguet Voir le message
    J'ai des doutes sur le fait que les alternatives conduisent un code généré plus compact.
    c'est facile, prenez un programme C++ n'utilisant pas les exceptions et compilez le en autorisant ou non les exceptions puis comparez les tailles.

    en C++ il n'est pas obligatoire de déclarer qu'une opération/fonction lève une exception => le code produit par le compilateur suppose que tout appel d'opération/fonction peut lever une exception => dés qu'une instance est créée en pile même de façon temporaire (conversion ou autre) le code doit se protéger et appeler le destructeur en cas de levée d'exception

    exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
     
    // fichier ex.c
    class C {
      public:
        C();
        ~C();
        void f(C, C);
    };
     
    void h()
    {
      C c1;
      C c2; // C() peut provoquer une exception => doit appeler delete c1 si besoin
     
      // l'instances temporaire creee en premier doit etre detruite 
      // si la creation de la seconde leve une exception
      // (j'ai utilise deux creations pour ne pas etre lie a leur
      // ordre d'appel)
      c2.f(C(), C());
    }
    suivant les modes de compilation :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    bruno@linux-ysqo:/tmp> g++ -O2 -c ex.c
    bruno@linux-ysqo:/tmp> size ex.o
       text    data     bss     dec     hex filename
        312       0       0     312     138 ex.o
    bruno@linux-ysqo:/tmp> g++ -O2 -c -fno-exceptions ex.c
    bruno@linux-ysqo:/tmp> size ex.o
       text    data     bss     dec     hex filename
        123       0       0     123      7b ex.o
    encore une fois on a rien sans rien, si vous avez peu de cas d'erreur alors vous aurez peu de code pour tester explicitement ces erreurs, si vous en avez beaucoup vous aurez également beaucoup de catch. Bien-sûr cela dépend aussi des cas d'erreur, si une erreur annule totalement une suite complexe d'appel d'opération/fonction alors il sera plus simple et clair d'utiliser une exception. Le charme et l'intérêt de la programmation c'est qu'il n'existe pas une solution optimale magique marchant dans tout les cas, quelques soient les fantasmes de décideurs n'ayant toujours pas compris ce qu'est cette discipline il s'agit pas d'un travail répétitif fait à la chaine mais d'un travail d'artisan au sens noble du terme
    Bruno Pagès, auteur de Bouml (freeware), mes tutoriels sur DVP (vieux, non à jour )

    N'oubliez pas de consulter les FAQ UML et les cours et tutoriels UML

  3. #23
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Points : 16 213
    Points
    16 213
    Par défaut
    Citation Envoyé par bruno_pages Voir le message
    c'est facile, prenez un programme C++ n'utilisant pas les exceptions et compilez le en autorisant ou non les exceptions puis comparez les tailles.
    Ce genre de test est doublement biaisé. Déjà la taille n'est pas forcément un bon indicateur des performances. Mais surtout, contrairement à ce que disait Jean-Marc, il ne compare pas un code gérant les erreurs avec des exceptions et un autre code gérant les mêmes erreurs avec les mêmes fonctionnalités, mais sans exceptions. Il compare juste deux codes dont aucun ne gère les erreurs.

    Si on part plutôt du principe que l'on veut un code gérant les erreurs, mais sans exceptions, il va falloir remplacer ces dernières par autre chose. Comparer le coût des exceptions à "rien" n'a alors pas de sens, ce qui est significatif est de comparer le coût des exceptions au coût du mécanisme alternatif.
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  4. #24
    Modérateur
    Avatar de bruno_pages
    Homme Profil pro
    ingénieur informaticien à la retraite
    Inscrit en
    Juin 2005
    Messages
    3 533
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 64
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : ingénieur informaticien à la retraite
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Juin 2005
    Messages : 3 533
    Points : 6 709
    Points
    6 709
    Par défaut
    vous avez mal compris ma démarche ou je n'ai pas été assez clair, je n'ai pas voulut être malhonnête, je voulais simplement attirer l'attention sur les conséquences induites par le fait que l'on compile ou non en autorisant les exceptions et montrer que cela a des répercussions partout dans le code généré.

    lorsque vous testez un retour ok/nok cela produit évidemment du code, lorsque vous écrivez un catch aussi, bien-sûr, le problème n'est pas là, dans l'exemple que je donne il n'y a effectivement ni l'un ni l'autre mais comme on peut le voir le code produit n'est vraiment pas le même.
    Bruno Pagès, auteur de Bouml (freeware), mes tutoriels sur DVP (vieux, non à jour )

    N'oubliez pas de consulter les FAQ UML et les cours et tutoriels UML

  5. #25
    Expert éminent

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Points : 6 911
    Points
    6 911
    Par défaut
    Citation Envoyé par bruno_pages Voir le message
    les conséquences induites par le fait que l'on compile ou non en autorisant les exceptions et montrer que cela a des répercussions partout dans le code généré.
    J'ai l'impression que tu surestimes les effets. Pour commencer, si une fonction ne jette pas d'exception on la déclare throw() et le compilateur ne doit pas supposer que cette partie est capable de jeter une exception, ensuite une bonne partie de l'overhead en espace que tu signales est dans des tables qui ne sont purement et simplement pas lues tant qu'il n'y a pas d'exception jetée -- je ne suis même pas sûr qu'elles sont mappées dans la mémoire virtuelle du programme.

    lorsque vous testez un retour ok/nok cela produit évidemment du code, lorsque vous écrivez un catch aussi, bien-sûr, le problème n'est pas là, dans l'exemple que je donne il n'y a effectivement ni l'un ni l'autre mais comme on peut le voir le code produit n'est vraiment pas le même.
    As-tu regardé plus loin que la taille du code?
    Les MP ne sont pas là pour les questions techniques, les forums sont là pour ça.

  6. #26
    Modérateur
    Avatar de bruno_pages
    Homme Profil pro
    ingénieur informaticien à la retraite
    Inscrit en
    Juin 2005
    Messages
    3 533
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 64
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : ingénieur informaticien à la retraite
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Juin 2005
    Messages : 3 533
    Points : 6 709
    Points
    6 709
    Par défaut
    Citation Envoyé par Jean-Marc.Bourguet Voir le message
    si une fonction ne jette pas d'exception on la déclare throw()
    tout a fait, mais il faut alors impérativement le faire partout, pour retomber à la même taille qu'avec l'option -fno-exceptions il faut donc :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    class C {
      public:
        C() throw();
        ~C() throw();
        void f(C, C) throw();
    };
    
    void h() throw()
    {
    ...
    }
    mais qui fera cela ? franchement pas moi
    le compilateur ne doit pas supposer que cette partie est capable de jeter une exception
    malheureusement la gestion des exceptions de C++ est catastrophique, ainsi le code suivant se compile sans erreur ni même warning y compris avec l'option -Wall
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    void f() throw()
    {
      throw 1;
    }
    en fait il n'y aura un problème qu'à l'exécution

    ce qu'il aurait fallut c'est que ne pas mettre the throw dans la signature interdise la levée d'exception et l'appel de fonctions/opérations levant des exceptions, donc quelque chose de 100% vérifiable à la compilation. Ca fait mal à dire mais sur ce coup Java à raison et C++ 100% tord

    As-tu regardé plus loin que la taille du code?
    pour cela il faut regarder l'assembleur produit, qui dépend bien-sûr du compilateur utilisé, dans le cas de g++ on remarque que la taille prise en pile pour h est de 0x56 avec exceptions potentielles et de 0x40 avec l'option les invalidant. Par contre les instructions exécutées sont au final les mêmes malgré un ordre différent.
    Bruno Pagès, auteur de Bouml (freeware), mes tutoriels sur DVP (vieux, non à jour )

    N'oubliez pas de consulter les FAQ UML et les cours et tutoriels UML

  7. #27
    Membre chevronné
    Avatar de Joel F
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Septembre 2002
    Messages
    918
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur en informatique
    Secteur : Service public

    Informations forums :
    Inscription : Septembre 2002
    Messages : 918
    Points : 1 921
    Points
    1 921
    Par défaut
    Question conne, mais au niveau du design de bibliothèque avec exception, j'ai pour habitude d'avoir en interne un THROW() qui est une macro qui fait effectivement un throw ou pas selon le mode de compilation. Ca permets de laisser à l'utilisateur le choix en toute connaissance de cause.

    Ou bien susi je à coté de la plaque ?

  8. #28
    Modérateur
    Avatar de bruno_pages
    Homme Profil pro
    ingénieur informaticien à la retraite
    Inscrit en
    Juin 2005
    Messages
    3 533
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 64
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : ingénieur informaticien à la retraite
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Juin 2005
    Messages : 3 533
    Points : 6 709
    Points
    6 709
    Par défaut
    Joel,

    dans le cas de g++ mettre throw() dans un profile est toujours accepté, c.a.d. y compris lorsqu'on utilise l'option -fno-exceptions, ce qui veut dire que l'utilisation d'une telle macro est inutile pour g++ (mais je en sais pas quel compilateur vous utilisez) ... et que le compilateur n'est pas totalement sadique
    Bruno Pagès, auteur de Bouml (freeware), mes tutoriels sur DVP (vieux, non à jour )

    N'oubliez pas de consulter les FAQ UML et les cours et tutoriels UML

  9. #29
    Membre chevronné
    Avatar de Joel F
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Septembre 2002
    Messages
    918
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur en informatique
    Secteur : Service public

    Informations forums :
    Inscription : Septembre 2002
    Messages : 918
    Points : 1 921
    Points
    1 921
    Par défaut
    j'aime pas throw() (et Herb Sutter non plus, ni le standard C++11 ).
    La je pensais plutot a eliminer entièrement les lancer d'exceptions de manière globale va une option de compilation et l'utilisation d'une amcro de controle (ce que fait Boost.Exception apr exemple).

  10. #30
    Membre chevronné
    Avatar de Goten
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    1 580
    Détails du profil
    Informations personnelles :
    Âge : 33
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 1 580
    Points : 2 205
    Points
    2 205
    Par défaut
    Ouai, les spécifications d'exception c'est pas ce que y'a de mieux...
    "Hardcoded types are to generic code what magic constants are to regular code." --A. Alexandrescu

  11. #31
    Expert éminent

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Points : 6 911
    Points
    6 911
    Par défaut
    Citation Envoyé par bruno_pages Voir le message
    mais qui fera cela ? franchement pas moi
    Le même genre de personnes que celles qui font attention à mettre des const où il faut. Avec l'avantage que const impose des contraintes sur les dépendances, un throw() non vérifié statiquement non.

    [quote]en fait il n'y aura un problème qu'à l'exécution

    J'aimerais bien un warning, et rien n'empèche à une implémentation de le donner, mais pas une erreur. Une vérification statique pour des spécifications d'exceptions similaires à la C++03, c'est une catastrophe pour le code générique, la maintenance et l'évolution (les exceptions sont un mécanisme adapté quand il faut traverser des couches, devoir les modifier quand une exception change est contre productif) même quand le mécanisme est présent depuis le début. Quand il ne l'est pas comme en C++, c'est pire.

    ce qu'il aurait fallut c'est que ne pas mettre the throw dans la signature interdise la levée d'exception et l'appel de fonctions/opérations levant des exceptions, donc quelque chose de 100% vérifiable à la compilation. Ca fait mal à dire mais sur ce coup Java à raison et C++ 100% tord
    Java, c'est bien le langage où il y a une classe d'exceptions qui ne sont pas vérifiée statiquement? Tous les inconvénients de l'absence de vérification statique, sans en avoir les avantages. Non merci.

    Citation Envoyé par Joel F Voir le message
    Question conne, mais au niveau du design de bibliothèque avec exception, j'ai pour habitude d'avoir en interne un THROW() qui est une macro qui fait effectivement un throw ou pas selon le mode de compilation. Ca permets de laisser à l'utilisateur le choix en toute connaissance de cause.

    Ou bien susi je à coté de la plaque ?

    La je pensais plutot a eliminer entièrement les lancer d'exceptions de manière globale va une option de compilation et l'utilisation d'une amcro de controle (ce que fait Boost.Exception apr exemple).
    J'ai pas d'expérience en la matière, je n'ai travaillé que sur des projets trop gros et avec trop de dépendances développées dans des contextes trop différents pour se permettre d'imposer de telles contraintes.

    Citation Envoyé par Joel F Voir le message
    j'aime pas throw() (et Herb Sutter non plus, ni le standard C++11 ).
    Personne, ou presque, n'aime throw() avec quelque chose dedans -- en tout cas pas moi. C++0X déprécie donc throw et introduit nothrow pour le seul cas où il est réellement utile, avec une légère différence par rapport à throw() (appel de std::terminate() plutôt que de unhandled() et avec un peu plus de latitude quant au moment). A noter qu'un nothrow vérifié statiquement serait tentant pour un nouveau langage, mais C++ a pour moi trop d'historique pour se le permettre (et j'ai le souvenir d'une mention de problèmes imposant de toucher aux éditeurs de liens, source d'objection supplémentaire, Loic tu te souviens des détails?)
    Les MP ne sont pas là pour les questions techniques, les forums sont là pour ça.

  12. #32
    Modérateur
    Avatar de bruno_pages
    Homme Profil pro
    ingénieur informaticien à la retraite
    Inscrit en
    Juin 2005
    Messages
    3 533
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 64
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : ingénieur informaticien à la retraite
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Juin 2005
    Messages : 3 533
    Points : 6 709
    Points
    6 709
    Par défaut
    Citation Envoyé par Jean-Marc.Bourguet Voir le message
    Le même genre de personnes que celles qui font attention à mettre des const où il faut.
    cette règle ne s'applique pas à moi car j'utilise const ... et râle auprès de ceux qui ne le font pas

    en fait j'ai heureusement déjà vu pas mal de personnes utilisant const mais jamais throw()
    Java, c'est bien le langage où il y a une classe d'exceptions qui ne sont pas vérifiée statiquement?
    oui ils ont fait les choses à moitié, et pas seulement dans ce cas puisque l'héritage est présent mais pas l'héritage multiple. ET puisqu'on parle de const ca aussi ca manque cruellement, surtout pour un langage ou le seul passage de paramètre est par pointeur, bref pour être sure que la chose appelée ne modifie par les args il faut les recopier. Mais c'est un autre débat

    A noter qu'un nothrow vérifié statiquement serait tentant pour un nouveau langage, mais C++ a pour moi trop d'historique pour se le permettre
    je suis bien d'accord, l'erreur concernant la non vérification statique des throw est une erreur initiale qu'il aurait fallut rapidement corrigée car après c'est impossible pour des raisons de compatibilité (à ce propos que les responsables de Qt4 soient mille fois maudits pour la non compatibilité avec QT3 , mais là aussi c'est un autre débat)
    Bruno Pagès, auteur de Bouml (freeware), mes tutoriels sur DVP (vieux, non à jour )

    N'oubliez pas de consulter les FAQ UML et les cours et tutoriels UML

  13. #33
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Points : 16 213
    Points
    16 213
    Par défaut
    Citation Envoyé par Jean-Marc.Bourguet Voir le message
    A noter qu'un nothrow vérifié statiquement serait tentant pour un nouveau langage, mais C++ a pour moi trop d'historique pour se le permettre (et j'ai le souvenir d'une mention de problèmes imposant de toucher aux éditeurs de liens, source d'objection supplémentaire, Loic tu te souviens des détails?)
    De mémoire, mais je n'en suis pas certain, l'idée était qu'imposer qu'une fonction nothrow n'ait le droit d'appeler que des fonctions déclarées nothrow serait bien trop restrictif par rapport au code actuel. Il fallait donc un mécanisme pour qu'une fonction nothrow ait le droit d'appeler soit des fonctions qui sont déclarées nothrow, ou des fonctions pour lesquelles le compilateur a pu vérifier qu'elles sont effectivement nothrow, même sans déclaration explicite du programmeur.Mais avec la compilation séparée, une telle information ne pouvait être stockée que... dans les fichiers objets générés, d'où modification du linker.
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  14. #34
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Vous souvenez-vous de ce que GotW a écrit à propos de throw()? Des choses pas gentilles.

    Si je veux déclarer qu'une fonction ne lance rien, je préfère encore utiliser le __declspec(nothrow) spécifique au compilateur, au moins je suis sûr qu'il ne fait pas ce massacre...
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  15. #35
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Points : 16 213
    Points
    16 213
    Par défaut
    Le nothrow sera de ce point de vue assez proche du __declspec(nothrow), mais en plus flexible.
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  16. #36
    Membre éprouvé
    Inscrit en
    Avril 2005
    Messages
    1 110
    Détails du profil
    Informations forums :
    Inscription : Avril 2005
    Messages : 1 110
    Points : 937
    Points
    937
    Par défaut
    Et beh, débat soutenu !

    Je nous vois mal désactiver l'option de compilation incluant les exceptions. Ce serait impossible en utilisant la moindre librairie, à commencer par la STL. Quitte à être contraint de l'activer, utilisons-la mais avec modération.

  17. #37
    Expert éminent

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Points : 6 911
    Points
    6 911
    Par défaut
    Citation Envoyé par camboui Voir le message
    Quitte à être contraint de l'activer, utilisons-la mais avec modération.
    L'important n'est pas d'utiliser les exceptions avec ou sans modération mais de les utiliser a bon escient.
    Les MP ne sont pas là pour les questions techniques, les forums sont là pour ça.

  18. #38
    r0d
    r0d est déconnecté
    Expert éminent

    Homme Profil pro
    tech lead c++ linux
    Inscrit en
    Août 2004
    Messages
    4 262
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : tech lead c++ linux

    Informations forums :
    Inscription : Août 2004
    Messages : 4 262
    Points : 6 680
    Points
    6 680
    Billets dans le blog
    2
    Par défaut
    Merci à tous pour vos contributions

    En fait, je fais partie de ceux qui n'aiment pas trop les exceptions. Je les utilise, mais vraiment avec parcimonie; et je ne les fais pas trop remonter (j'ai eu à travailler récemment sur une API qui gérait tout avec des exceptions et je crois que ça m'a traumatisé). Car dans les exceptions il y a plusieurs choses qui me gènent; en fait j'ai l'impression que cette histoire d'exception en c++ est un peu une "beta-feature" du langage, une fonctionnalité en cours de développement en quelque sortes. M'enfin bon ce n'est pas le sujet, et je pense qu'on peut faire aussi bien avec que sans exceptions (dans le sens de l'utilisation des exceptions pour le transport de l'erreur). Et vice-versa.

    Je ne me prononce pas pour le 0x11, dont je ne connais que vaguement les grandes lignes.

    Le fait est que, et contrairement à ce que tout le monde ici semble affirmer (ou pour le moins, ne pas infirmer), le principe de "toute erreur doit être traitée" est un bon principe pour enseigner le c++, mais dans la réalité, c'est loin d'être toujours vrai. Je travaille sur des applications de plus en plus grosses, sur lesquelles travaillent de plus en plus de développeurs, et concrètement ce qu'il se passe c'est qu'on se retrouve à implémenter un module donné sans savoir précisément la manière dont ce module va être utilisé. Et bien souvent, la moitié des erreurs qu'on va gérer dans ce module n'auront aucun intérêt pour le module qui va l'utiliser. Et bien souvent, on n'en sait rien à l'avance. Un cahier des charges suffisemment précis ert qui permet d'avoir une vision exhaustive de la gestion des erreurs, ça n'existe pas dans la vraie vie.
    « L'effort par lequel toute chose tend à persévérer dans son être n'est rien de plus que l'essence actuelle de cette chose. »
    Spinoza — Éthique III, Proposition VII

  19. #39
    Expert confirmé

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Points : 4 551
    Points
    4 551
    Par défaut
    Citation Envoyé par bruno_pages Voir le message
    Je n'aime pas les exceptions, comme leur nom l'indique finalement elle ne devraient être utilisées qu'exceptionnellement .
    A tous ceux qui n'aiment pas les exceptions et qui pensent qu'elles doivent être utilisées de manière exceptionnelle, je leur rappelle que le terme est dérivé d'une exception processeur - qui est un traitement non standard, pas un traitement exceptionnel. Les exceptions regroupent les erreurs importantes (division par 0) et les interruptions matérielles (appui d'une touche sur le clavier). La dernière fois que j'ai vérifié, l'appui d'une touche sur le clavier d'un ordinateur n'était pas un traitement exceptionnel.

    Et puis, qu'est-ce que ça veut dire exceptionnel ? Si je ne me trompe, ça veut juste dire que ce n'est pas la règle. Ça ne fait pas intervenir de notion de fréquence. Si vous réfléchissez à notre langue, les verbes que nous utilisons le plus souvent sont être, avoir et faire. Ce sont trois conjugaisons exceptionnelles...

    Citation Envoyé par bruno_pages Voir le message
    Comme il faut appeler les destructeurs sur les instances placées en pile lors de la descente liée à une levée d'exception le code produit pas le compilateur est beaucoup plus grand que sans (option de compilation).
    Moui... Peut-être... Non...

    Dans les compilateurs récents (MS et GNU), la gestion des exceptions est activée par défaut. Pour GCC, il faut l'option -fno-exception pour les désactiver, et pour les compilateurs MS, l'option /EHSc est activée par défaut quand on crée un projet dans Visual Studio (il faut donc aller dans Properties > C++ > Code Generation pour la désactiver). Idem d'ailleurs pour RTTI (-fno-rtti pour GCC, et un petit tour dans les options de langage pour Visual Studio).

    Pourquoi ?

    Principalement pour troisraisons :

    1) Celui qui lance des exceptions dans une boucle ou les performances sont critiques est plus ou moins un imbécile. Que celui-là se rende compte de son erreur grâce aux performances dégradées ne me pose pas de problème.

    2) Dans le cas ou les exceptions sont utilisées correctement, elles ne grèvent pas les performances de l'application (ou très peu) - puisque tout traitement d'exception est par définition hors du traitement normal de l'application.

    3) et puis damned, la librairie standard émet des exceptions ! Et plutôt 2 fois qu'une ! Elle nous dit qu'il est préférable d'utiliser std::vector<>::at() au lieu de std::vector<>::operator[] ; elle nous recommande d'utiliser ::operator new() en lieu et place de ::operator new(nothrow_t) ; etc. Si on veut que ces exceptions soient bien traitées par le code client, il est nécessaire d'autoriser leur traitement au moment de la compilation.

    Et puis, qu'est-ce que les exceptions rajoutent dans le code qui le rend plus lent ? Tout se passe au niveau des appels de fonction, qui sont déjà extrêmement lents sur un processeur x86. Des informations sont rajoutées sur la pile de manière à autoriser le stack unwinding. Dépiler ces informations en cas de retour normal d'une fonction ne coute rien (pour simplifier, l'instruction asm leave X est exécutée et dépile X mots ; quelque soit X, l'instruction s'exécute dans le même temps). Bien évidemment, le traitement des exceptions est lourd - mais celui-ci est fort logiquement peu courant. A noter que le problème lié à l'exécution des destructeurs est un faux problème, puisque ceux-ci sont aussi invoqués en cas de fonctionnement nominal.

    Il faut se rappeler aussi que la taille du code n'est pas liée à sa vitesse d'exécution. Un exemple simple : une boucle déroulée a de bonnes chances de s'exécuter plus rapidement qu'une boucle non déroulée, même si le code, au final, est plus important. Petit code ne rime pas avec grandes performances. Il rime avec petit code, c'est tout. Bien sûr, si la boucle a été trop déroulée, il se peut que le code ne tiennent pas sur une ligne de cache - et dans ce cas, raccourcir la boucle peut améliorer les performances. Mais si vous en arrivez là dans votre passe d'optimisation, c'est que vous essayez de grappiller le pour-cent restant à grappiller - et donc que vous avez déjà récupéré les 80% venant de problèmes algorithmiques.

    Citation Envoyé par bruno_pages Voir le message
    Je suis d'accord avec les défauts indiqués à propos du getlasterror.
    Sans parler que :
    * le code est globalement plus complexe et donc plus difficile à maintenir.
    * peu de fonction de l'API Windows documentent exactement l'ensemble des valeurs que peut prendre GetLastError() en cas d'erreur, ce qui ne simplifie pas non plus le développement.
    * les API Windows évoluent avec le temps, et les erreurs qu'elles peuvent lever évoluent aussi - ce qui peut poser encore des problèmes de maintenance sur un produit livré cette fois (puisque le comportement peut être modifié au runtime).

    Citation Envoyé par bruno_pages Voir le message
    Mais plutôt que de rendre simplement un booleen disant ok/nok il faut utiliser une classe (disons Status) permettant de savoir à fois si c'est ok/nok et dans le cas nok qu'elle est l'erreur, celle-ci pouvant si besoin être enrichie/transformée par les appels imbriqués. Comme la chose est assez souvent recopiée (le retour d'une méthode devenant le retour de la méthode qui l'utilise + mémorisation locale etc) et qu'il faut que cela aille vite le contexte décrivant l'erreur et qui est lui aussi une instance (au niveau de Status c'est un pointeur vers une interface) à une gestion de type compteur faite dans Status pourqu'il soit libéré à la destruction du dernier Status qui l'a contenu. Bien évidemment il faut explicitement tester les retours de méthode retournant un Status pour savoir si il y a une erreur, et les 'vraies' valeurs retournées par les méthodes utilisent des paramètres de sortie, mais que voulez-vous, on a rien sans rien.

    <code />
    Je suis rassuré : le traitement que tu présente est beaucoup plu léger que celui qui pourrait être lié à un traitement d'exception, et le code est plus simple à maintenir

    Grosso-modo, c'est la même chose, sauf qu'au lieu de laisser le compilateur effectuer le stack unwinding, c'est le programmeur qui le fait.

    Citation Envoyé par bruno_pages Voir le message
    [edit]au fait, pas besoin de critiquer le fait que toutes les opérations soient inline, j'ai fais exprès pour limiter la hauteur du code [/edit]
    Si le fond pêche, la forme n'a que peu d'importance
    [FAQ des forums][FAQ Développement 2D, 3D et Jeux][Si vous ne savez pas ou vous en êtes...]
    Essayez d'écrire clairement (c'est à dire avec des mots français complets). SMS est votre ennemi.
    Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Café. C'est dépassé tout ça.
    Et si vous êtes sages, vous aurez peut être vous aussi la chance de passer à la télé. Ou pas.

    Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.

  20. #40
    Membre émérite
    Avatar de white_tentacle
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    1 505
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 1 505
    Points : 2 799
    Points
    2 799
    Par défaut
    Citation Envoyé par Emmanuel Deloget Voir le message
    3) et puis damned, la librairie standard émet des exceptions ! Et plutôt 2 fois qu'une ! Elle nous dit qu'il est préférable d'utiliser std::vector<>::at() au lieu de std::vector<>::operator[] ; elle nous recommande d'utiliser ::operator new() en lieu et place de ::operator new(nothrow_t) ; etc. Si on veut que ces exceptions soient bien traitées par le code client, il est nécessaire d'autoriser leur traitement au moment de la compilation.
    Je suis globalement d'accord avec ton propos, à l'exclusion de ta remarque sur at(). at() est pour moi un non-sens : tu as tous les moyens à ta disposition pour t'assurer avant l'appel de operator[] que celui-ci va réussir : tu dois faire comme ça, et pas tenter d'accéder à l'élément puis te raccrocher à une exception si jamais ça ne marche pas.

    En revanche, new est un très bon example : tu ne peux pas savoir en l'appelant s'il va réussir ou pas --> nécessité de récupérer l'erreur à posteriori.

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo