Journal Pourquoi empaqueter KDE prend-il du temps ?

Posté par  (site web personnel) . Licence CC By‑SA.
Étiquettes :
27
17
août
2014

Je signale aux fans de KDE, aux contributeurs et tous ceux qui bossent sur une distribution, la passionnante discussion entre empaqueteurs de diverses distribution sur le blog de Johnattan Riddell.
Elle commence par un long article de Riddell qui détaille les soucis et les difficultés d'empaquetage liés à KDE ou Qt sur Kubuntu. Suivent des réponses tout aussi longues de responsables Fedora, OpenSuse et Debian (peut-être d'autres quand vous lirez).
Voici l'adresse sur le planet KDE https://blogs.kde.org/2014/08/13/upstream-and-downstream-why-packaging-takes-time

  • # En vrac

    Posté par  . Évalué à 10.

    Où on apprend que le C++, c'est tout pourri, que gstreamer est bien mieux que ffmpeg, que la minification c'est le mal et que la gestion des licences ça prend du temps.

    « Rappelez-vous toujours que si la Gestapo avait les moyens de vous faire parler, les politiciens ont, eux, les moyens de vous faire taire. » Coluche

    • [^] # Re: En vrac

      Posté par  (site web personnel) . Évalué à -6.

      Depuis 1992 on reproche les mêmes choses encore et encore au c++ et c'est pleinement justifié, d'où java et gtk. Le problème c'est qu'on est obligé de ne pas utiliser plein de fonctionnalités du c++ pour qu'il reste proche du c. Et Qt y arrive très bien.

      Les nouvelles normes foutent la merde.

      • [^] # Re: En vrac

        Posté par  . Évalué à 7. Dernière modification le 18 août 2014 à 12:08.

        GTK… tiens, je vais marcher dedans, pour le fun.

        Me semblait que si GTK est plus utilisé que Qt, c'est parce qu'à l'origine, Qt n'était totalement libre. Les deux semblent plus ou moins autant utilisés en C++, au pifomètre.

        Depuis 1992 on reproche les mêmes choses encore et encore au c++

        Marrant, je pense qu'en fait, le premier standard (qui est de 98) à dû résoudre pas mal de problèmes, par exemple les soucis de compatibilité entre les compilo (du moins ceux qui acceptent de respecter les standards).

        Les nouvelles normes foutent la merde? Je ne pense pas, honnêtement, je pense même que c'est tout le contraire.
        Par exemple, si je prend C++11:
        * std::array permets d'utiliser les algo standards avec des tableaux à dimension fixe, et donc de ne pas réinventer la roue. Ce n'est pas une mauvaise chose pour moi.
        * std::unique_ptr, uniquement possible grâce à la move semantic, permets de lutter contre les memory leaks en augmentant la garantie qu'un seul propriétaire contrôle un espace mémoire (on peut contourner, comme toujours en C++, et je parie que cette possibilité est conservée du fait qu'on doive interagir avec du C…).
        * for( auto i : foo ){ i*=10; }, c'est quand même vachement plus lisible (et sûr) que les alternatives plus anciennes for( int i = 0; i < foo.size(); ++i ){ foo[i]*=10; } ou for( std::vector<int>::iterator it = foo.begin(); it != foo.end(); ++it ){ *it*=10; } non?

        Ça, c'est pour les critiques sur les nouvelles normes, mais pour être juste, je me dois de mentionner une fonctionnalité de C++03 (ou 98?) que seul commeau à implémenté, conseillant fortement aux autres dev de compilo de ne pas le faire, parce que ça n'apporte au final rien, semble-t-il. Quelques recherches devraient pouvoir en dire plus.

        Maintenant, dire que C++ c'est de la merde contre le C… allez, je marche encore :)

        Ça me fait assez sourire quand je vois des gens dire que C++ c'est de la merde comparé au C, en fait. Il suffit de lire du code C pour comprendre ce que C++ à ajouté.
        La RAII permets de rendre un code bien plus maintenable et sûr, et les templates ou les fonctions inline permettent de s'affranchir en grande partie des macros, ce qui évite pas mal d'emmerdes.

        Avant, les jeux, comme quake par exemple, étaient stables. Ils étaient codés en C. Il faut dire que, les malloc y étaient rares, tous les tableaux étant statiquement alloués, donc les problèmes de mémoire simples à éviter.
        Ceci dit, j'ai quelques souvenirs de jeux pour lesquels le dépassement de buffer est simple à causer. En même temps, c'est logique: en C, il faut vérifier le retour de la moindre fonction, manuellement, pour être sûr que tout s'est passé comme prévu.
        En C++, et dans tous les langages évolués, la mécanique des exceptions permets de s'affranchir de ce problème. Mais ici, l'avantage du C++ sur d'autres langages, c'est qu'on peut s'affranchir de ces fameuses exceptions.

        Et quand on lit un code source C qui utilise de manière intensive de la construction de chaînes de caractères, quelle joie que de voir des buffer alloués avec des tailles impressionnantes, et ensuite une succession de strcat, parce que strcpy( foo, bar ); strcat( foo, "world" ); c'est vrai que c'est tellement plus lisible que foo += bar + "world";.

        Je vais m'arrêter là, je pense. Je veux bien que l'on compare C++ avec Java, C# ou d'autres, mais avec le C… soyons sérieux un instant, le seul avantage que je puisse voir du C sur C++ réside de son ABI stable en toutes circonstances (utile pour les plugins).

        Dans le cas du C++, l'ABI n'est stable que si l'on n'utilise pas de méthodes virtuelles, voire si l'on utilise des structures pures. En d'autres mots, si on se restreint à des fonctionnalités C.
        Ah, non, il y a aussi un cas ou j'ai eu un comportement différent selon les compilos, mais il faut avouer que j'avais cherché la merde, et le workaround était relativement simple.
        Ça, ça bug: foo( bar[++i], bar[++i], bar[++i] ); avec VS2008 "i" faut la même valeur à chaque fois, donc la même valeur est utilisée dans les 3 arguments, contrairement à ce que GCC fait. Et les deux comportements semblent être standards, pour une question d'optimisation. Pour l'info, le workaround était, de mémoire, ceci: foo( (bar[++i]), (bar[++i]), (bar[++i]) );.
        Mais c'était une construction sale, qui n'avait pour unique but que celui de réduire encore un peu le nombre de lignes de code d'une encapsulation que j'avais fait autour d'une API sur laquelle je n'avais aucun contrôle et qui sans ça demandait de répéter les informations jusqu'à 3 fois, dans 3 fonctions différentes… (powerbuilder, vous connaissez?).

        • [^] # Re: En vrac

          Posté par  (site web personnel) . Évalué à -4.

          Je comprends pas, si gtk a eut le soutient de tout les gros acteurs, et est en c, c'est que l'abi du cpp pue (même aujourd'hui). Si java a eut du succès c'est sûrement pas grâce aux qualité du c++. Qt utilise des pointeurs vers des struct pour masquer les évolutions de la structure interne et sauver son ABI.

          Perso je ne critique pas le c++ dans sa globalité, mais après 10 ans de c++, des 10aines de millions de lignes de code compiler, la certification de compilateur et un gros paquet d'optimisation CPU de code c++, je ne peux toujours pas prétendre connaitre le c++ globalement sur toutes les plateformes, je ne connais bien que le sous ensemble de ce qu'en fait Qt.

          • [^] # Re: En vrac

            Posté par  . Évalué à 2.

            Je comprends pas, si gtk a eut le soutient de tout les gros acteurs, et est en c, c'est que l'abi du cpp pue (même aujourd'hui).

            Pas de tous les gros acteurs, quand même, au moins nokia à soutenu Qt, au point de l'acheter.
            Sinon, WxWidgets, même si je sais que ce n'est pas apprécié ici, à été utilisé par google (en version 2.9, je n'arrive pas à retrouver le lien en moins de 60s, mais si tu insistes, j'essaierais plus fort).
            Bref, il n'y à pas que GTK, loin de là et heureusement.

            Et pour ce qui est de l'ABI du C++, oui, c'est sûr, c'est moche, mais il y à des solutions, un peu plus bas un commentaire parle de pimpl. Je me suis aussi amusé à faire une archi de plug-in un jour, et donc me suis pas mal renseigné. Certes, c'est la merde, c'est clair, mais on peut contourner.

            Si java a eut du succès c'est sûrement pas grâce aux qualité du c++.

            En effet, Java est bien plus simple à maîtriser que C++, ce qui fait qu'il est intéressant pour pas mal de monde. Il y à aussi une grande quantité de dev Java, contrairement au C++.
            Ce genre de choses jouent.

            Qt utilise des pointeurs vers des struct pour masquer les évolutions de la structure interne et sauver son ABI.

            Effectivement, c'est une des solutions utilisées pour contourner le problème.

            e ne peux toujours pas prétendre connaitre le c++ globalement sur toutes les plateformes, je ne connais bien que le sous ensemble de ce qu'en fait Qt.

            Je suis d'accord, C++ est un langage réellement riche, ce qui peut faire peur. Mais personne n'est obligé d'utiliser C++ au complet, non plus.
            Dis-moi, est-ce plus simple d'optimiser la charge CPU en C qu'en C++? Et si oui, pourquoi? Je suis réellement intéressé par ta réponse pour le coup.

        • [^] # Commentaire supprimé

          Posté par  . Évalué à 10.

          Ce commentaire a été supprimé par l’équipe de modération.

          • [^] # Re: En vrac

            Posté par  . Évalué à -3.

            Mais si sa fonction foo est invariante par permutation de ses arguments, il ne se chaut de l'ordre d'évaluation des arguments, tant qu'ils ne sont pas évalués « en même temps ».

            J'ai plutôt l'impression que tant qu'on ne sait pas se que fait foo c'est un peu prématuré de conclure sur une erreur du code.

            • [^] # Commentaire supprimé

              Posté par  . Évalué à 3. Dernière modification le 19 août 2014 à 11:48.

              Ce commentaire a été supprimé par l’équipe de modération.

              • [^] # Re: En vrac

                Posté par  . Évalué à 4.

                Alors pour moi, l'ordre non spécifié des arguments ne veut pas dire que le compilateur a le droit de les évaluer en parallèle.

                Je dis qu'une fonction foo(.,.,.) peut être invariante à une permutation des parametres, c'est à dire foo(a,b,c)=foo(a,c,b)=foo(b,a,c)=foo(b,c,a)=foo(c,a,b)=foo(c,b,a). Il y a plein de fonctions qui ont cette caractéristique, par exemple, somme, moyenne, produit, ecart-type, variance, mediane

                Dans ce cas il n'importe guère que le compilateur évalue foo(bar[11],bar[12],bar[13]) ou foo(bar[13],bar[11],bar[12]) tant qu'il n'évalue pas foo(bar[11],bar[11],bar[11]).

                Ce que je veux dire c'est que le débat ne doit pas être sur la non spécification de l’évaluation de l'ordre des arguments, mais sur la possibilité d'une évaluation parallèle.

                je n'ai toujours pas vu (Je peux l'avoir loupée) ta brillante solution à De la probabilité que votre RAID vous abandonne…

                Pour répondre à ta question, je suis parti sur une exploration d'une partie de la littérature sur la modélisation des pannes, l'hypothèse de vieillissement sans mémoire n'étant à mais yeux raisonnable qu'en première approximation. Et je suis persuadé que raisonner en première approximation est une erreur dans ce cadre. Cette première approximation est pour moi une sous-évaluation du processus réel, et ne pose aucun problème dans le cadre de la revue que tu cite, puisqu'ils s'en servent pour dire que même sous cette hypothèse, le RAID avec deux niveaux de redondance est insuffisant. Ton attaque, à dire donc que je contredirai cette publication est donc ridicule.

                J'ai fini assez rapidement la description du modèle, mais je n'ai pas trouvé rapidement de moyen clair d'ajuster les paramètres, donc aucun moyen de l'illustrer et de montrer sa différence. Je l'ai fait après, mais le thread était mort entre temps. Il semble qu'il y ai au moins une personne intéressée par la réponse, sachant que le thread est maintenant définitivement mort, je te répondrai sous la forme d'un journal. Tu aurai pu le demander avec respect et sans sarcasme, cela aurai fonctionné de ma même façon. Quand à ta remarque sur la publication de l'ACM, elle est hors-de-propos, ne cherchant pas à montrer la même chose. Et quand bien même elle le serait, la contradiction sur le choix des hypothèses est la base du débat scientifique.

                • [^] # Re: En vrac

                  Posté par  . Évalué à 8.

                  Alors pour moi, l'ordre non spécifié des arguments ne veut pas dire que le compilateur a le droit de les évaluer en parallèle.

                  f(i++,i++,i++) est un comportement indéfini, et pas un comportement défini par l'implémentation. D'une part la norme du C (et aussi du C++ dans ce cas je crois bien) ne garantit rien sur l'ordre d'évaluation des arguments (contrairement à Java par exemple, qui garantit que l'évaluation des paramètres se fait de gauche à droite). D'autre part, comme le comportement est indéfini, l'évaluation de f(i++,i++,i++) peut renvoyer n'importe quoi qui arrange le compilateur pour ce qui est de la valeur passée de i. Ça signifie entre autres que pour le compilateur, n'importe quelle valeur de i convient, même des valeurs qui ne devraient « logiquement » pas exister. Imaginons le code suivant :

                  int i = 4;
                  f(i++,i++,i++);

                  Le « triplet » de i peut être évalué comme f(4,5,6) (ou une combinaison différente de 4 5 et 6) et i aura comme valeur finale 7. Mais il peut aussi se résoudre comme f(0,0,0). « Hein ? De quoi ? » Ben oui : le comportement est indéfini, et le compilateur peut faire ce qu'il veut. Et ce n'est pas forcément reproductible (un implémenteur de compilos un peu pervers pourrait décider d'affecter des valeurs aléatoires dans le cas de comportements indéfinis).

                  Lire aussi ici, qui explique tous les tenants et aboutissants.

                • [^] # Commentaire supprimé

                  Posté par  . Évalué à 5. Dernière modification le 20 août 2014 à 01:26.

                  Ce commentaire a été supprimé par l’équipe de modération.

          • [^] # Re: En vrac

            Posté par  . Évalué à 0. Dernière modification le 19 août 2014 à 15:37.

            C'est un peu le béaba du c/c++.

            Désolé, je n'ai jamais lu le standard, donc non, pas spécialement le b-a-ba. Oui, je sais que c'était un problème dans mon code, et, si, mon workaround avait résolu le problème. Je ne suis juste plus sûr que c'était exactement ça, peut-être que c'était une fonction inline. Mais c'est sûr que c'était un truc crade, par contre.

            • [^] # Re: En vrac

              Posté par  . Évalué à 4.

              Peu de gens connaissent le standard du C (par ex. C99) sur le bout des doigts, et c'est encore plus vrai pour C++. Cependant, c'est effectivement un piège connu de C/C++: les opérateurs qui ont des effets de bord ne doivent pas être utilisés lorsque la variable qu'ils affectent est présente plusieurs fois dans une expression sans point de séquence pour donner un ordre aux opérations. Dit autrement :

              a[i] = a[i++];
              a[++i] = a[i];
              i = f(i++);
              f(i++,++i);

              … Et toutes les autres variantes sont des comportements non-spécifiés ou des comportements indéfinis, car il n'y a pas d'ordre d'évaluation claire, et le fait qu'ajouter des parenthèses ait résolu ton problème l'époque est de la pure chance : ton code peut (et va sans doute) casser si tu compiles avec un autre compilateur, ou (possiblement) si tu le recompiles avec une version du compilateur plus récente/plus ancienne.

              • [^] # Re: En vrac

                Posté par  . Évalué à 2.

                Je pense que je n'avais pas ajouté de simples parenthèses, en fait. La mémoire… ça remonte ce truc :)

                Me semble qu'en fait, j'avais lu quelque part que, dans le cas ou les paramètres contiennent des appels à des fonctions, alors ces fonctions sont évaluées dans l'ordre, que la fonction soit inlinée ou pas, et j'avais donc utilisé cette méthode (je ne sais pas pourquoi j'ai pensé aux parenthèses, l'autre jour, mais bon, c'est un code d'il y à 2 ans et impliquant un langage que je préférerait oublier). Le résultat est alors devenu cohérent sur les 2 compilateurs que j'utilisais: G++ (quoique j'utilisais peut-être déjà clang++, je ne sais plus) sous Debian testing, et visual studio 2008 (je sais, c'est un IDE, mais je connais pas le nom du compilo sous jacent).

                Franchement, d'ordinaire, je ne me serais pas amusé à faire ce genre de trucs casse-gueule, de la même façon que d'habitude, j'évite les macros comme la peste. Dans le cas que j'ai cité, j'ai utilisé de façon assez massive des macros, et en un endroit cette chose, en combinaison avec des macros qui résultaient en ces fameux appels, justement.
                L'idée était relativement simple (tout ce que je dis est un souvenir d'il y à 2 ans, je préviens. Depuis, j'ai dormi pas mal…):

                Le langage powerbuilder se base sur une sorte de machine virtuelle, de la même façon que Java, et expose une API C++ assez mal fichue selon moi à l'époque (bien que maintenant je comprenne un peu plus les raisons, mais je pense toujours que c'est améliorable).
                Cette API permets, malgré tout, de pouvoir "injecter" du code: ajouter des classes, en fait, appelables ensuite depuis un programme PB classique comme si les classes en question étaient codées en PB.
                Par contre, côté code natif, c'était assez pénible: des chaînes de caractère à passer 3 fois à divers moments de l'init, une visibilité nulle quant à pourquoi le code sigsegv, et pour récupérer les valeurs reçues lors d'un appel d'une méthode par PB, il fallait écrire, pour chaque argument, un truc de ce genre (dans le genre, donc pas exactement, j'ai un très gros doute pour le type): "pbvm->arg(5)->get_int(x);" et bien sûr, ça pouvait encore planter parce que si on se trompait de type, ça crashait sans dire pourquoi, lors de l'appel par la pbvm.
                Donc, j'avais fait une surcouche à cette API, qui permettait de pouvoir injecter des classes en faisant dans une classe "proxy" (le terme n'est pas exact) un simple héritage d'une part d'une classe de ma surcouche, et d'autre part de la classe C++ qui fait réellement le boulot (histoire de pouvoir vérifier sur une plate-forme non windows que ça compile/marche, sans avoir besoin de devoir accéder à la PBNI --l'API powerbuilder-- ).
                Dans cette classe proxy, au début, il fallait au minimum autant de lignes de code par méthode que d'arguments powerbuilder, ce qui était lourd et générateur d'erreur.
                Donc, vu que j'avais un peu de temps, j'ai essayé (et réussi, même si je n'était pas vraiment très fier de la propreté du code de cette partie de ma surcouche) de faire une sorte de langage basé sur les macros du C qui permette de réduire tout le boilerplate de chaque méthode rendue accessible à 1 ligne: la ligne de déclaration de boilerplate.

                Genre:

                #include "npbni.hpp" // ma surcouche
                #include "foo.hpp" // la classe qui fait le véritable taf
                
                class pb_foo : public foo, public npbni<NON_VISUAL_PNBI> // on pouvait exporter 2 types de classes, à la mécanique sous-jacente légèrement différente, donc template pour pas que ce soit trop pénible
                {
                RETURN_INT foo( TYPE_FLOAT, TYPE_INT, TYPE_STRING );
                };

                Je ne me souviens pas exactement des noms et du fonctionnement des macros, c'est juste pour donner un ordre d'idée.

            • [^] # Commentaire supprimé

              Posté par  . Évalué à 7.

              Ce commentaire a été supprimé par l’équipe de modération.

              • [^] # Re: En vrac

                Posté par  . Évalué à 3.

                tu ne te considères plus avancé que le béotien

                Je ne me considère plus comme un débutant total, mais je reste loin d'être bon, encore trop à apprendre.

                Ne le prend pas mal

                Si je devais prendre mal des commentaires constructifs, je serait vraiment bête :) au contraire, je te remercie de prendre le temps.
                Et si je prenais mal un commentaire sur internet, je n'irai pas sur LinuxFR xD (parce qu'il faut avouer que ça balance quand même assez sévère parfois)

                Le RAII est apparu pour résoudre un problème introduit par les exceptions.

                Je ne sais pas pourquoi c'est apparu, mais c'est également utile dans un code qui n'utilise pas les exceptions. Par exemple, quand on utilise une lib C, disons, SDL, pouvoir s'abstenir d'allouer et désallouer manuellement la mémoire à chaque fois que l'on rencontre une erreur est utile.
                Je vois plutôt la RAII comme une alternative aux GC, qui à l'avantage de permettre quand on ne se sert plus d'un objet de libérer les ressources qu'il utilisait immédiatement, comme une connexion, chose qui est faite avec une latence dans le cas d'un GC (puisqu'il ne passe pas en permanence derrière le programme, si je ne m'abuse).

                La façon dont c'est fait en C++ apporte trop de désavantages

                Je viens de regarder la section pointée, et il apparaît que la plupart des inconvénients cités soient liés aux éditeurs de textes et compilateurs, le reste étant un problème de temps de compilation (il faudrait ajouter que dans le cas d'une lib proprio, on ne peut pas masquer le code j'imagine).

                Des langages comme Ada

                ADA m'intéresse, mais la dernière fois que j'ai essayé de m'y mettre, je n'ai pas réussi à trouver de doc satisfaisante pour mettre le pied dedans.

                Les fonctions inline existent aussi en C depuis le C99 (15 ans !!!).

                Ok mea culpa.

                C'est un des plus grands problèmes du c++, amha. On a ajouté, ajouté et encore ajouté.

                Je suis d'accord, mais il me semble qu'ils invoquent la compatibilité avec le C comme excuse, en voulant l'enrichir, ce qui rend je pense l'ensemble plus complexe.
                S'il cassaient la compatibilité avec le C, tout en gardant le fait d'être compilé et de ne pas avoir de GC, ça rendrait peut-être C++ (ou le langage qui en résulterait) plus gérable.

                Par exemple, pourquoi n'y a-t-il pas une construction W pour construire du sucre syntaxique ?

                Effectivement, c'est quelque chose qui serait vraiment agréable. D'ailleurs, je suppose que ça m'aurait évité de commettre l'erreur plus haut, puisque j'avais fait ça dans le but de construire justement une syntaxe pour éviter de se fader du boilerplate à n'en plus finir… Je n'ai pas (encore) regardé l'article que tu cites, mais je pense avoir compris l'idée?

                • [^] # Re: En vrac

                  Posté par  (site web personnel, Mastodon) . Évalué à 6.

                  ADA m'intéresse, mais la dernière fois que j'ai essayé de m'y mettre, je n'ai pas réussi à trouver de doc satisfaisante pour mettre le pied dedans.

                  Rhoo, y a plein de trucs !!
                  - le wikibook
                  - un document pour programmeurs C++/Java
                  - un cours en français que je viens de trouver mais qui fait entièrement sous Windows
                  - Ada distilled
                  - Les cours de Daniel Feneuille en français mais qui ne couvrent pas les dernières versions
                  - l'université Adacore

                  Nan, franchement, tu fais pas d'efforts ;)

                  • [^] # Re: En vrac

                    Posté par  . Évalué à 2.

                    Roh, pourquoi j'ai pas été voir sur wikibook… enfin un truc ou il y à une procédure pour compiler sans avoir besoin d'IDE!

                    Merci bien!

                • [^] # Re: En vrac

                  Posté par  (site web personnel) . Évalué à 2.

                  Je vois plutôt la RAII comme une alternative aux GC, qui à l'avantage de permettre quand on ne se sert plus d'un objet de libérer les ressources qu'il utilisait immédiatement, comme une connexion, chose qui est faite avec une latence dans le cas d'un GC (puisqu'il ne passe pas en permanence derrière le programme, si je ne m'abuse).

                  Même dans les langages à GC, tu as des méthodes close() dans ce genre de cas.
                  Le rôle du GC est de gérer la mémoire, pas de libérer des ressources.

                  • [^] # Re: En vrac

                    Posté par  . Évalué à 3.

                    Les méthodes close, il faut les appeler explicitement, contrairement aux destructeurs. Et la RAII (Resource Acquisition Is Initialisation) sert à gérer les ressources, toutes les ressources, sinon ça s'appèlerait MAII (Memory Acquisition Is Initialisation).
                    La mémoire étant une ressource comme une autre, elle tombe aussi sous le coup de la RAII.

              • [^] # Re: En vrac

                Posté par  . Évalué à 5.

                Je vais traiter ces deux points en même temps car ils sont intimement liés. Le RAII est apparu pour résoudre un problème introduit par les exceptions. Oui, oui, la gestion des exceptions introduits des problèmes. Les exceptions sont ruptures de séquences, elles peuvent survenir à de nombreux endroits. Elles sont comme des GOTO mais des GOTO invisibles. Et Dieu sait si les goto (mal/trop utilisés) sont une bombe à retardement (Je ne vais pas revenir sur le célèbre article de Dijkstra Go To Statement Considered Harmful). Donc, nous avons une sorte de goto implicites. Nous pouvons avoir des sauts de quasi n'importe où dans le programme vers autre part, pire les exceptions peuvent même faire des sauts dans la pile d'appel, càd sortir de multiples appels de fonctions d'un seul coup. Cela crée énormément de points de sortie potentiel d'une fonction.

                Tout structure de contrôle est un GOTO caché que ce soit le if, le while ou le for par exemple. Ce qui pose problème ce n'est pas les exceptions, c'est la gestion des exceptions par le C++. En Java le fait d'obliger à déclarer les exceptions qu'une méthode lève (mis à par les RuntimeException) réduit de beaucoup le problème de lecture du flow d’exécution. Ça permet de réellement aller vers le "je ne peux pas oublier de cas d'erreur sans l'indiquer explicitement dans mon code".

                Après les exceptions posent pleins de problèmes (la performance, la gestion correct de où doit-on catcher l'exception, etc).

                Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)

                • [^] # Re: En vrac

                  Posté par  . Évalué à 2.

                  Après les exceptions posent pleins de problèmes (la performance,

                  Pour la performance, il semble que pour les implémentations actuelles, il n'y à de problème qu'en cas de levée d'exception, cependant.
                  Et d'ailleurs, pendant que j'y suis, il me semble bien qu'il soit possible de désactiver la gestion des exceptions en C++. Je n'ai aucune idée de comment ça réagit en cas d'erreur après (jamais utilisé), mais le flag de compilation -fno-except me semble fait pour ça.

                  Maintenant, la façon dont je me sers des exceptions personnellement, c'est pour que quand ça plante, ça plante en disant pourquoi, et pas avec un simple "segmentation fault" qui nécessite du temps passé à déboguer pour retrouver l'info. Donc la performance…

                  • [^] # Re: En vrac

                    Posté par  . Évalué à 2.

                    Si tu désactives les exceptions que ton programme en lève une, voici ce qui se passe avec gcc:

                    #include <iostream>
                    
                    struct MyException {};
                    
                    void raise_exception(void) { throw MyException(); }
                    
                    int 
                    main(void)
                    {
                        raise_exception();
                        std::cout << "HELLO\n";
                        return 0;
                    }

                    Ligne de compilation:

                    g++ -fno-exceptions -fno-rtti -o exceptions except.cc

                    Sortie:

                    except.cc: In function ‘void raise_exception()’:
                    except.cc:15:23: error: exception handling disabled, use -fexceptions to enable
                         throw MyException();
                    
                    • [^] # Re: En vrac

                      Posté par  . Évalué à 3.

                      Oui, enfin, là tu la lèves toi-même donc le compilo fait son taf et t'envoie paître, normal. Je pensais plus au comportement de la STL, ou de linker avec une lib externe. Dans le cas de la STL, je suppose que ça ne pose pas de problème et qu'il existe une version sans exceptions, mais à voir le comportement de GCC, j'imagine que pour les lib externes, on ne peux "juste" pas linker.

                      • [^] # Re: En vrac

                        Posté par  . Évalué à 3.

                        Certes. Donc en transformant le code ci-dessus et en séparant en deux fichiers (et en passant par un ar histoire de faire de l'un des deux fichiers objet une « bibliothèque »), la compilation se passe « bien » (pas d'erreur). Lancer le programme me donne :

                        terminate called after throwing an instance of 'MyException'
                        Aborted (core dumped)
                        

                        … Ce qui est peu ou prou ce que je voudrais qu'il arrive : le programme plante avec la « bonne » exception. Lorsque je tente de compiler un code C++ avec des conteneurs STL (vector et queue) « vides » (même en forçant la taille à 0 pour le vector), si je fais un front() puis pop() sur la queue<int>, je récupère 0.

                        • [^] # Re: En vrac

                          Posté par  . Évalué à 2. Dernière modification le 25 août 2014 à 11:29.

                          … Ce qui est peu ou prou ce que je voudrais qu'il arrive : le programme plante avec la « bonne » exception.

                          Non, selon moi, si tu désactives les exceptions, ça veut dire que tu vas vérifier tout le nécessaire avant et après chaque appel de fonction, et agir en conséquence. Prendre la main toi-même plutôt que rester en pilotage automatique en somme.

                          Je considérerai l'appel à std::terminate plutôt comme un "bug", pour ma part, et ce même si j'ai horreur de la programmation défensive (comme toi à priori, je préfère un bon gros crash direct qu'une saleté de petit bug insidieux qui poursuis son chemin des heures avant de finir par exploser). Du coup je trouve logique l'undefined behavior (perso avec clang, j'ai une sigsegv --logique-- quand je tente d'accéder à front() juste après avoir instancié un vector d'int) que tu as avec la STL sans exception :)

                          En tout cas merci pour le test.

                          • [^] # Re: En vrac

                            Posté par  . Évalué à 2.

                            Euh, on n'a pas la même version de clang alors (la mienne est la v3.4). Quand je compile le code suivant avec clang++, voilà ce que j'obtiens:

                            #include <iostream>
                            #include <vector>
                            
                            int 
                            main(void)
                            {
                                std::vector<int> v;
                                for (int i = 0; i < 10; ++i) {
                                    int ii = v.at(i+10);
                                    std::cout << "ii = " << ii << std::endl;
                                }
                                std::cout << "HELLO\n";
                                return 0;
                            }

                            La sortie est :

                            terminate called after throwing an instance of 'std::out_of_range'
                              what():  vector::_M_range_check
                            Aborted (core dumped)
                            

                            Obtenir un segfault avec vec[i] serait normal, car c'est comme ça que l'API de std::vector fonctionne : at lève une exception si on est hors des limites, mais [] fonctionne « comme » un tableau C, et donc c'est au programmeur de faire gaffe.

                            • [^] # Re: En vrac

                              Posté par  . Évalué à 2.

                              Euh… en fait je crois que je me suis juste méchamment embrouillé… les effets secondaires du week-end je suppose: mea culpa

                • [^] # Re: En vrac

                  Posté par  . Évalué à 4. Dernière modification le 21 août 2014 à 19:14.

                  Tout structure de contrôle est un GOTO caché que ce soit le if, le while ou le for par exemple.

                  Je ne suis pas d'accord pour dire ça comme ça. Au niveau assembleur, un goto est bien entendu un branchement inconditionnel, et peut viser une adresse arbitraire (jmp <ADRESSE_ARBITRAIRE>). La seule sémantique de goto est de se brancher là où on lui dit. La sémantique du if est celle d'un branchement conditionnel, qui va à une adresse relative (jne <DÉPLACEMENT_RELATIF>). Les structures de boucle while et for font appel à un branchement conditionnel et un branchement inconditionnel. On part de :

                  while ( condition ) {
                      corps;
                  }
                  apres_la_boucle;

                  On arrive à quelque chose de ce genre (avec une « traduction » asm naïve) :

                  BOUCLE:
                  if (!condition) goto APRES_LA_BOUCLE; // par exemple: jge APRES_LA_BOUCLE
                  corps;
                  goto BOUCLE; // jmp BOUCLE
                  APRES_LA_BOUCLE:
                  apres_la_boucle;

                  Mais il y a une sémantique très spécifique qui limite où le saut peut s'effectuer (si tu veux, on pourrait dire qu'un if ou une boucle ont certes une étiquette implicite, mais on sait exactement où elle est placée). Avec des branchements inconditionnels « relatifs », de type break ou continue, c'est la même chose: dans le cas du break on effectuera un jmp APRÈS_LA_BOUCLE et dans le cas d'un continue ce sera jmp BOUCLE, mais tout est confiné correctement. Dans tous les cas, tu as la garantie que tu ne peux pas atterrir dans une portion de code arbitrairement, comme par exemple:

                  int a = 0;
                  
                  void foo(int n) {
                    if (n == 0) goto LABEL; // wah trop bien hé, t'as vu l'optim' ?
                    // reste du code...
                  }
                  
                  // plein de fonctions entre les deux
                  
                  int bar(void) {
                  LABEL:
                    ++a;
                  }

                  Les exceptions sont quelque chose d'intermédiaire entre le goto et les branchements conditionnels selon moi: elles ressemblent à une forme de « gotos typés ». Exactement comme avec un goto, il faut spécifier des labels à des endroits précis (grâce à la construction try { … } catch(...)). Contrairement à un goto, il y a un minimum de maîtrise sur où le saut peut arriver (car try/catch est bien une structure de contrôle), mais les sauts peuvent être bien plus longs que la portée lexicale d'un bloc (comme c'est le cas pour if/while/for/break/continue).

                  Ce qui pose problème ce n'est pas les exceptions, c'est la gestion des exceptions par le C++. En Java le fait d'obliger à déclarer les exceptions qu'une méthode lève (mis à par les RuntimeException) réduit de beaucoup le problème de lecture du flow d’exécution

                  Ça par contre je suis tout à fait d'accord : forcer à déclarer quelles exceptions peuvent être levées permet au compilateur d'engueuler le programmeur qui spécifie des « étiquettes » n'importe comment, et de préciser s'il veut traiter une exception ou non.

                  Ça n'empêche pas qu'il est parfaitement possible d'utiliser les exceptions non pas comme un mécanisme de gestion d'erreurs, mais comme un mécanisme de « goto contrôlé ».

                  • [^] # Re: En vrac

                    Posté par  . Évalué à 3.

                    Les exceptions sont quelque chose d'intermédiaire entre le goto et les branchements conditionnels selon moi: elles ressemblent à une forme de « gotos typés ».

                    Je ne suis pas d'accord. Ou du moins ça n'est pas différent des autres structures de contrôles existantes. L'idée c'est toujours la même : avoir des structures de contrôles qui sont les plus expressives possibles, pour remplacer les saut conditionnels ou non qui ne portent aucune sémantique. La boucle for est là pour itérer, la boucle while pour boucler, les switch pour énumérer, les exceptions pour gérer des erreurs,… C'est peut être une construction plus complexe que les autres, mais ça n'est rien de plus qu'une autre encapsulation de saut.

                    Tu parle du fait que le saut peut être long c'est vrai en C++ en Java non, parce que tu doit réellement raisonner au sein de ta méthode, les exceptions levé font partie du contrat d'interface au même titre que la valeur de retour.

                    À noter pour ceux que ça intéresse un excellents articles des mongueurs de perl sur le sujet http://articles.mongueurs.net/magazines/linuxmag72.html

                    Si tu veux voir des goto bien moches bien cachés je te conseil de regarder les duff's device.

                    Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)

                    • [^] # Re: En vrac

                      Posté par  . Évalué à 2.

                      Je connais bien le Duff's device. C'est une très chouette horreur, légale en C (et C++ aussi je pense). :)

                    • [^] # Re: En vrac

                      Posté par  . Évalué à 2.

                      Ça fait un bon moment que je n'ai pas fait de Java, mais je ne vois pas ce qui m'empêche de faire ceci (attention, mon style en Java va sentir bon le cru 2005, je préviens :-) :

                      public class BaseCase {
                          public static void main (String[] args) {
                              try {
                                  BaseCase.compute(10);
                              } catch (Exception e) { 
                                  System.out.println(e);
                              }
                          }
                      
                          public static void compute(int n) throws Exception {
                              System.out.println("Computing...");
                              if (n == 0) {
                                  throw new Exception("Base case reached!");
                              } else {
                                  compute(n-1);
                              }
                          }
                      
                      }

                      … Où comment court-circuiter la pile d'appels récursifs pour « sortir » d'une récursion profonde (enfin c'est plus compliqué que ça, mais je pense que tu vois où je veux en venir). Alors oui en Java tu es forcé d'annoncer que tu jettes des exceptions et lesquelles, mais tu peux à peu près toujours jeter une exception de base juste pour marquer un endroit du control-flow qui t'intéresse, et oui tes méthodes d'instance et de classe vont dire « throws Exception ». Ça n'empêche pas que tu vas potentiellement utiliser un code qui s'appuie sur les exceptions pour faire des choses crades et « sauter » d'un appel de fonction à l'autre. Comme je le disais avant, évidemment c'est plus limité qu'un goto classique, mais il est quand même relativement aisé de voir comment un programmeur peut être « perverti » par la puissance qu'apportent les exceptions.

                      Sinon, il y a longtemps, j'avais un chef de projet qui avait sans doute été brûlé avec la gestion des exceptions en C++ (qui, il faut bien l'avouer, est plus compliquée qu'en Java), et qui du coup nous avait interdit/fortement déconseillé de les utiliser, et du coup faisait ceci:

                      String errStr = "";
                      while ( true ) {
                          errStr = "Condition1 a échoué";
                          if ( !condition1 ) break;
                          // ...
                          errStr = "Condition2 a échoué";
                          if ( !condition2 ) break;
                          // ...
                      
                          // etc.
                      }

                      … Et du coup on avait le droit à une « re-création » du goto limitée à un bloc de code …

                  • [^] # Commentaire supprimé

                    Posté par  . Évalué à 3. Dernière modification le 22 août 2014 à 01:38.

                    Ce commentaire a été supprimé par l’équipe de modération.

                    • [^] # Re: En vrac

                      Posté par  . Évalué à 2.

                      Anéfé. :)

                      Bon c'est grossier, mais de toute manière un goto peut toujours aider à faire un COMEFROM (que je ne connaissais pas :-)).

                      int err = 0;
                      bool condition = true;
                      TRY: 
                      if (err != 0) gestion_erreur(err); 
                      condition = try(...); // traitement ... 
                      CATCH:
                      if (condition == false) {
                          err = quelle_erreur(); 
                          goto TRY; 
                      }
                      
                      // le "try/catch" a fonctionne
                • [^] # Commentaire supprimé

                  Posté par  . Évalué à 2.

                  Ce commentaire a été supprimé par l’équipe de modération.

                  • [^] # Re: En vrac

                    Posté par  . Évalué à 3.

                    Est-ce que tu as la moindre idée si cela peut générer un saut ?

                    En C++, non. En Java si tu fait :

                    a.add(b).add(c).add(d);

                    Tu sais si ça peut générer un saut ou pas (ton compilateur te le dira).

                    C'est bien pour ça que je dis :

                    Ce qui pose problème ce n'est pas les exceptions, c'est la gestion des exceptions par le C++.

                    Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)

                    • [^] # Re: En vrac

                      Posté par  . Évalué à 2.

                      En C++, non. En Java si tu fait :

                      Dépend du type des valeurs que tu additionnes. Si ce sont des entiers, non. Si ce sont des std::string, oui. Quand on utilise un type, on est censé savoir ce que ça implique. Même si j'avoue que je trouve très dommage le fait que l'on ait pas de moyen automatisé de savoir si une exception peut être lancée sans jamais être interceptée (en C++) ainsi que le fait que l'on ne puisse pas préciser quelles exceptions peuvent être lancées par une fonction.

                      Pour le coup, j'ai une question sur Java: quand on déclare une fonction qui appelle des fonction qui peuvent lancer, il faut déclarer qu'elle peut lancer les exceptions des fonctions qu'elle appèle ou non? Si c'est le cas, n'est-ce pas trop lourd?

                      • [^] # Re: En vrac

                        Posté par  . Évalué à 4.

                        Dépend du type des valeurs que tu additionnes. Si ce sont des entiers, non. Si ce sont des std::string, oui. Quand on utilise un type, on est censé savoir ce que ça implique. Même si j'avoue que je trouve très dommage le fait que l'on ait pas de moyen automatisé de savoir si une exception peut être lancée sans jamais être interceptée (en C++) ainsi que le fait que l'on ne puisse pas préciser quelles exceptions peuvent être lancées par une fonction.

                        Tu es alors dépendant de la documentation de ce que tu utilise, ce n'est plus le langage qui t'aide.

                        Pour le coup, j'ai une question sur Java: quand on déclare une fonction qui appelle des fonction qui peuvent lancer, il faut déclarer qu'elle peut lancer les exceptions des fonctions qu'elle appèle ou non?

                        Bien sûr comment voudrait-tu faire autrement ? Si tu as 2 méthode fa et fb et que fa appel fb et que fb lève une FooException, si fa ne gère pas l'exception de fb il doit impérativement la déclarer. Sinon un code qui appel fa ne pourrait pas savoir qu'il risque de prendre une FooException.

                        Si c'est le cas, n'est-ce pas trop lourd?

                        Je trouve pas, il faut raisonner en top-down. Commence par déterminer ton contrat qu'est-ce qui intéresse ou non l'utilisateur de ta méthode ? Tout ce qui ne l'intéresse pas, il doit soit l'ignorer soit être encapsulé pour que ce soit intelligible pour lui.

                        Je ne trouve pas que ce soit plus lourd qu'une gestion d'erreur par retour de valeur avec un goto éventuel la vers la fin de la méthode comme c'est fait dans le noyau.

                        Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)

        • [^] # Re: En vrac

          Posté par  . Évalué à 2. Dernière modification le 20 août 2014 à 14:58.

          Je vais peut être dire une connerie, ne connaissant pas le type de bar
          mais les versions suivantes ne corrigeraient pas le problème ?

          // dans le cas d'un tableau
          foo(*(bar + i+ 1 ), *(bar+i+2), *(bar+i+3));
          bar+=3;
          
          // ou 
          
          typeMuche &p1=bar[++i];
          typeMuche &p2=bar[++i];
          typeMuche &p3=bar[++i];
          foo(p1,p2,p3);

          En C, comme en C++ (et comme en java), j'ai appris que les ++ et—ne s'utilisent que lorsque l'élément incrémenté n'est référencé qu'une seule fois dans la ligne, sinon le comportement est indéfini pour la majorité des gens relisant le code :)

          Il ne faut pas décorner les boeufs avant d'avoir semé le vent

      • [^] # Re: En vrac

        Posté par  (site web personnel) . Évalué à 4. Dernière modification le 18 août 2014 à 13:16.

        Les nouvelles normes foutent la merde.

        J'aimerai que tu eclaires ma lanterne et ceux de tous les devs C++ ici sur "en quoi les nouvelles normes foutent la merde".

        Le C++11 ne rend pas pire ou meilleur l'ABI C++, c'est toujours le même bousin qu'en C++98 ou C++03, rien n'a changer.

        Depuis 1992 on reproche les mêmes choses encore et encore au c++ et c'est pleinement justifié, d'où java et gtk

        Sans vouloir troller, entre maintenir une ABI C++ et utiliser Gtk, je prefere encore le cauchemar de l'ABI, c'est peu dire.

        Quand à java, il est vrai qu'avoir une machine virtuelle évite effectivement les problèmes d'ABI…. simplement parce que la notion de binaire persistant n'existe pas en java.

        Tu échanges juste un problème de compatibilité binaire contre un problème d'over-head à chaque lancement de la JVM…. Si c'était la solution parfaite, ça ferait bien longtemps que Java et dotnet aurait remplacer C++ pour tous les logiciels clients lourds… Hors ça n'est jamais arrivé et n'arrivera probablement jamais.

        • [^] # Re: En vrac

          Posté par  . Évalué à 4.

          simplement parce que la notion de binaire persistant n'existe pas en java.

          J'aurai dis que c'est parce qu'en Java, il n'y à qu'une machine, une API, et un seul compilo (le tout, de référence, hein, je suis au courant qu'il existe des clones, mais l'interop est-elle si parfaite dans les faits? J'en sais rien…) en fait, alors que pour C++, il y à une pléthore de machines, une chiée d'OS différents qui impactent, et une flopée de compilos.
          Forcément, ça rend les choses moins simples.

        • [^] # Re: En vrac

          Posté par  (site web personnel) . Évalué à -1.

          J'arrive pas a comprendre comment on peut soutenir que l'ABI du c++ n'est pas une GROSSE MERDE.

          Pourtant, je préfère 100 fois Qt à Gtk.

          La dernière fois que j'ai fait du c++, je n'ai pas réussi à linker un pointeur de fonction vers une fonction compiler avec un compilateur c. Le B.A.-BA. Je sais pas quelle pédanterie il aurait fallu (genre un proxy bien dégueulasse)…

          Je ne comprends même pas que ce soit compliqué. Avant ça ne posait aucun problème et heureusement, peut être n'est-ce pas dû a la norme, mais pour moi c dramatique.

          • [^] # Re: En vrac

            Posté par  (site web personnel) . Évalué à 0.

            La dernière fois que j'ai fait du c++, je n'ai pas réussi à linker un pointeur de fonction vers une fonction compiler avec un compilateur c

            1. PEBKAC
            2. Idée absolument stupide

            git is great because linus did it, mercurial is better because he didn't

          • [^] # Re: En vrac

            Posté par  . Évalué à 0. Dernière modification le 18 août 2014 à 15:25.

            La dernière fois que j'ai fait du c++, je n'ai pas réussi à linker un pointeur de fonction vers une fonction compiler avec un compilateur c. Le B.A.-BA. Je sais pas quelle pédanterie il aurait fallu (genre un proxy bien dégueulasse)…

            Donnes-nous donc un PoC de ce qui rate, on pourra peut-être t'expliquer le pourquoi du comment?

            Ceci dit, je me demande déjà ce que tu appelles lier un pointeur de fonction vers une fonction C… j'ai suffisamment codé en utilisant des lib C et pourtant je n'ai pas souvenir d'avoir eu ce type de problème?

            Un truc genre

            #include <cstdio>
            
            int hello(int i, float j){puts("hello ");return 0;}
            int world(int i, float j){puts("world!");return 0;}
            
            int main(void)
            {
              int (* pFoo) (int, float);
              pFoo = hello;
              pFoo(1,0.2);
            
              pFoo = world;
              pFoo(1,0.2);
            
              return 0;
            }

            compile parfaitement et fonctionne sans souci.

            Bon, si c'est un souci de linkage, sache que j'ai fait le même genre de trucs avec la SDL 1.2, pour être précis, j'ai utilisé du std::unique_ptr avec SDL_Surface, en lui passant en destructeur la fonction qui remplace le destructeur. Donc, j'ai déjà fait aussi avec un truc compilé par un compilo C.

            • [^] # Re: En vrac

              Posté par  (site web personnel) . Évalué à 0.

              Sauf que dans mon cas, word a été compilé avec un compilateur c dans une autre lib. Pas g++. C'est tellement gros comme manque que je pense que j'ai merdé.

              En 2005, je pouvais linker sans problème des lib fortran 77 compiler en 1996 avec du c++. Maintenant si on peut plus utiliser un pointeur de fonction c, compilé avec un compilo c avec du c++, c'est que les concepteurs du c++ sont dans les nuages.

              • [^] # Re: En vrac

                Posté par  . Évalué à 2. Dernière modification le 20 août 2014 à 12:48.

                As-tu essayé d'encapsuler les include avec extern "C"?

                fichier hello.c:

                #include <stdio.h>
                
                int hello( int i, float j){puts("hello ");return 0;}

                hello.h:

                #ifndef HELLO_H
                #define HELLO_H
                
                extern int hello( int i, float j);
                
                #endif

                fichier world.c:

                #include <stdio.h>
                
                int world( int i, float j){puts("world! ");return 0;}

                world.h:

                #ifndef WORLD_H
                #define WORLD_H
                
                extern int world( int i, float j);
                
                #endif

                main.cpp:

                extern "C"
                {
                #include "hello.h"
                #include "world.h"
                }
                
                int main()
                {
                    int (* pFoo) (int, float);
                    pFoo=hello;
                    pFoo(1,0.2);
                
                    pFoo=world;
                    pFoo(1,0.2);
                    return 0;
                }

                compilation et exécution:

                $ gcc hello.c -shared -fPIC -o libhello.so
                $ gcc world.c -shared -fPIC -o libworld.so
                $ clang++ -L/tmp/tmp -o test main.cpp -lhello -lworld
                $ LD_LIBRARY_PATH=./ ./test
                hello 
                world!

                La même technique résout-elle ton problème? (j'ai utilisé Clang++ et non G++ pour le C++ pour le fun, en théorie ça ne change rien, c'était histoire d'utiliser 2 compilo, mais bon ils sont compatibles donc… mais j'ai rien d'autre sous la main.)

                En tout cas, ce PoC marche, si ton cas ne marche pas, encore une fois, poste un extrait de code, qu'on puisse te répondre sans être dans le brouillard.

    • [^] # Re: En vrac

      Posté par  . Évalué à 4.

      J'ai plutôt l'impression que la cause d'emmerdes majeures des packageurs, c'est la quasi absence de préoccupation du packaging des dev de KDE (et peut-être des gros projets de manière générale?):

      • pas de version stable, chaque nouvelle version ajoute de nouvelles fonctionnalités, et donc bugs
      • archives monolithiques même si les sources que ça inclue sont relatives à plusieurs modules distincts

      Et un commentaire intéressant du mainteneur Debian:

      Not so far ago, discussing something with some upstream (not Qt), he told me "just make -j6 upload and be done". My first reaction was "I wish I could do that". My "most capable" system is a dual core with "just" 4GB of RAM, so I have to resort to swap for being able to build beasts like webkit.

      Bon, à priori il y a aussi des problèmes de communication entre les mainteneurs des diverses distro, qu'ils semblent avoir envie de résoudre d'ailleurs…

      A noter que certains mainteneurs parlent de problèmes liés au fait que gnome et kde utilisent des versions incompatibles des mêmes lib. Ça, je trouve ça vraiment très, très drôle (je doute que ce soit leur cas, m'enfin…)

      Sinon, le seul commentaire au sujet de ffmpeg dans cette discussion, c'est pour dire qu'a cause de problème de licence, c'est plus casse-pied que gstreamer, je n'ai rien noté sur le plan technique.

      Tout ceci étant dit, ce sujet est intéressant (celui qui est pointé) pour ceux qui ne comprennent pas vraiment les différences entre les distros (comme moi): pour le coup, vu qu'ils parlent des problèmes et des solutions apportés par les divers systèmes de paquet, je vais enfin pouvoir y voir un poil plus clair dans cette jungle.

      • [^] # Re: En vrac

        Posté par  . Évalué à 4.

        Not so far ago, discussing something with some upstream (not Qt), he told me "just make -j6 upload and be done". My first reaction was "I wish I could do that". My "most capable" system is a dual core with "just" 4GB of RAM, so I have to resort to swap for being able to build beasts like webkit.

        Ben c'est un peu dommage si un mainteneur d'un gros paquet debian est limité par ce genre de contingences. Dual core 4go de ram c'est à peine l'entrée de gamme aujourd'hui :-/
        C'est dommage qu'ils ne soient pas plus sponsorisés.

        • [^] # Re: En vrac

          Posté par  . Évalué à 3.

          Les mainteneurs Debian peuvent très bien le faire avec leurs machines persos. Et franchement, 4Go de RAM, c'est peut-être l'entrée de gamme, mais sérieux, c'est déjà énorme, il n'y à que les super grosses applications qui peuvent bouffer tant à la compilation, et j'ai envie de dire que je ne suis pas sûr que ce soit toujours justifié.

          Bon, il faut aussi dire que compiler avec GCC ne doit pas aider, c'est un véritable goinfre ce compilo, et j'ai constaté une diminution drastique de la RAM utilisée en utilisant clang il y à 2 ans (un projet qui faisait swapper à la compilation mon netbook et son unique Go de RAM avec 3 thread me laissait 200Mo utilisables avec clang et 4 thread).

          • [^] # Re: En vrac

            Posté par  . Évalué à 2.

            Et franchement, 4Go de RAM, c'est peut-être l'entrée de gamme, mais sérieux, c'est déjà énorme, il n'y à que les super grosses applications qui peuvent bouffer tant à la compilation, et j'ai envie de dire que je ne suis pas sûr que ce soit toujours justifié.

            C'est peut-être beaucoup dans l'absolu, mais c'est quasi ce qu'on trouve dans une phablette et juste deux fois plus que ce qu'on trouve dans un téléphone. Donc relativement ce n'est pas si énorme, même si je me soupçonne vaguement que ça sert aussi à faire joli dans la fiche technique.
            Après, la RAM plus y en a mieux c'est. Ca fait un bon gros cache et c'est très utile à la compilation.

            • [^] # Re: En vrac

              Posté par  . Évalué à 2. Dernière modification le 19 août 2014 à 16:30.

              C'est bien d'avoir de la RAM, oui, c'est sûr.

              Maintenant, il n'y à pas que la taille^W capacité qui compte, mais aussi la fréquence. Je me demande si l'accès à la RAM d'un téléphone est aussi rapide que celui à celle d'un PC portable?

              • [^] # Re: En vrac

                Posté par  . Évalué à 2.

                Je donne ma langue au kitteh, je ne suis pas particulièrement spécialiste du domaine, entre toutes les subtilités fréquence/CAS, etc.
                Si je me réfère juste à la fiche kikipedia de la LPDDR3, il y a un truc qui dit que ce qui est déployé sur les exynos samsung double et octo cœur est au niveau de la SODIMM PC3-12800 de 2011. Ce qui est déjà pas mal.

        • [^] # Re: En vrac

          Posté par  . Évalué à 4.

          Ben c'est un peu dommage si un mainteneur d'un gros paquet debian est limité par ce genre de contingences. Dual core 4go de ram c'est à peine l'entrée de gamme aujourd'hui

          Mouais bof ; encore là, il ne s'agit que de compilation et non d'utilisation1, mais personnellement, j'aimerais qu'on oblige les développeurs à travailler sur des machines anémiques ; ça leur ferait prendre conscience que les logiciels qu'ils développent peuvent devenir obèses/mal foutus/RAMivores/CPUvores alors qu'ils ne sont seront pas les seuls à tourner sur les machines des utilisateurs et qu'ils devraient se préoccuper un minimum de leurs performances de façon à ce qu'ils soient au moins utilisables sur de petites configs (et légers comme des plumes sur des grosses configs).
          Mais bon, O tempora, O mores, qu'il disait.


          1. mais si on n'est plus en capacité de compiler ce qu'on utilise, c'est qu'il y a quand même quelque chose de faisandé au royaume du logiciel libre. 

          • [^] # Re: En vrac

            Posté par  (site web personnel) . Évalué à 2.

            j'aimerais qu'on oblige les développeurs à travailler sur des machines anémiques

            J'y pense aussi parfois.
            Mais, ma machine tourne avec KDE 4.13, c'est un Pentium IV avec 700 Mo de mémoire. Cette bécane doit avoir 12 ans. Je ne peux donc pas vraiment me plaindre.
            Reste le web, où ça devient vraiment très très casse-pied. Et Firefox aussi, de plus en plus gourmand.

            Cela dit, mettons nous à la place des développeurs : développer pour une puissance accrue (les bécanes actuelles) offre plein de nouvelles possibilités. Tu veux les frustrer ?

            "La liberté est à l'homme ce que les ailes sont à l'oiseau" Jean-Pierre Rosnay

            • [^] # Re: En vrac

              Posté par  . Évalué à -3.

              Cela dit, mettons nous à la place des développeurs : développer pour une puissance accrue (les bécanes actuelles) offre plein de nouvelles possibilités. Tu veux les frustrer ?

              Ben, ça dépend de comment on définit la frustration, de comment elle apparaît.
              Si on est frustré parce qu'on peut/doit écrire un logiciel un peu fignolé de manière à être assez robuste et peu gourmand, c'est-à-dire ce qui, pour un programmeur, me semble devoir procurer, outre la satisfaction d'un travail bien fait, quelque plaisir dans le fait de trouver l'algo, la petite optimisation ou la réorganisation qui fait gagner 40% de mémoire ou 60% de CPU ; alors oui, ça ne me dérangerait pas de les frustrer.
              C'est sûr que si on ne trouve satisfaction que dans l'utilisation du toolkit/framework/whatever_it_is_called_this_year bancal du mois dans le dernier langage à la mode pas encore finalisé sur la dernière plateforme-surcouche-de-surcouche-de-surcouche apparue, ça va frustrer aussi.

              • [^] # Re: En vrac

                Posté par  . Évalué à 5.

                qui fait gagner 40% de mémoire ou 60% de CPU

                En vrai tu crois vraiment que ça se passe comme ça ? Genre tu réfléchis 20 minutes, tu réorganise 3 lignes dans ton programme et c'est partie pour le logiciel de 3D qui prend 4o en mémoire et se lance sans problème sur une calculatrice de collégien ?

                Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)

                • [^] # Re: En vrac

                  Posté par  . Évalué à -2.

                  Aurais-je éventuellement par mégarde laissé échapper une ébauche de sous-entendu qui pourrait signifier quelque chose vaguement en rapport avec les propos que tu me prêtes avant même de partir dans des exagérations qui se veulent cassantes ?

                  Non. Merci. Au revoir.

                  Et sinon, oui, si le programme est vraiment mal torché au départ, et ce n'est pas ce qui manque, on peut rapidement trouver des pistes d'améliorations. En vrai !

                  • [^] # Re: En vrac

                    Posté par  . Évalué à 6. Dernière modification le 25 août 2014 à 08:44.

                    Aurais-je éventuellement par mégarde laissé échapper une ébauche de sous-entendu qui pourrait signifier quelque chose vaguement en rapport avec les propos que tu me prêtes avant même de partir dans des exagérations qui se veulent cassantes ?

                    Je me permet de répondre au question que tu ne semble pas me poser : oui.

                    Tu as sciemment utilisé des propos cassants en expliquant que les "développeurs" pourraient par une "petite optimisation" gagner "40% de mémoire ou 60% de CPU".

                    A ton cassant, ton cassant et demi.

                    Mais je t'en pris montre nous tous ces exemples de programmes (tu remarquera les "s" montrer un projet obscure sur github qui peut correspondre ça ne montre rien) si mal codés qu'avec une petite optimisation on arrive à de grands gains, donne des éléments à ce que tu avance au lieu d'être méprisant pour rien et là ce que tu dis pourra être pris au sérieux.

                    Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)

              • [^] # Re: En vrac

                Posté par  . Évalué à 3.

                40% de mémoire ou 60% de CPU

                En général, c'est l'un ou l'autre, mais rarement les deux, à moins d'avoir codé comme un goret au départ.

                "Quand certains râlent contre systemd, d'autres s'attaquent aux vrais problèmes." (merci Sinma !)

                • [^] # Re: En vrac

                  Posté par  . Évalué à -2.

                  Ah OK, c'est peut-être pour ça que j'avais marqué « ou » juste dans le bout de phrase que tu cites, alors…

                  Néanmoins, dans certains cas, diminuer la mémoire utilisée peut mécaniquement entraîner un gain de perf CPU (histoires de caches et Cie ).

      • [^] # Re: En vrac

        Posté par  . Évalué à 2.

        La 4.11 est une version LTS de mémoire (la dernière stable étant la 4.13

        • [^] # Re: En vrac

          Posté par  . Évalué à 3.

          C'était la dernière version de Plasma et pour le coup, Plasma 4.11 est supporté pendant 2 ans. Cependant, les autres applications (qui forment la Software Collection) ne sont pas prises en compte dans ce support.

          « Rappelez-vous toujours que si la Gestapo avait les moyens de vous faire parler, les politiciens ont, eux, les moyens de vous faire taire. » Coluche

  • # Quelqu'un peut-il m'expliquer le problème avec l'ABI de KDE

    Posté par  . Évalué à 3.

    Much of what we package are libraries and if one small bit changes in the library,
    any applications which use that library will crash. This is ABI and the rules
    for binary compatibility in C++ are nuts. Not infrequently someone in KDE will
    alter a library ABI without realising.

    Je ne comprends pas l'argument. Il dit que changer l'ABI est un problème parce qu'il empaquète des bibliothèques et donc à chaque fois il faut recompiler ce qui en dépend. Mais il s'occupe des bibliothèques KDE, pas de la libc… Si un développeur KDE change l'ABI de KDE, il faut recompiler KDE certes, mais c'était justement ce qu'il allait faire pour mettre à jour KDE, donc quel est le problème ? (d'après ce que je vois dans mes logs, KDE met de toute façon à jour tous ses paquets à chaque version mineure même s'il n'y que quelques corrections par-ci par-là).

    Un commentaire plus bas par un type de Debian A Debian Qt/KDE (but mostly Qt) packager's POV reprend le thème :

    if there is an incompatible change aka API/ABI change we need to rebuild all the stuff
    that links against the library which did the change. […] Now we have 30000+ source
    packages in the archive […] Main point here: it's definitely not just "push to unstable
    and be done" when API/ABI or some other major change happens.

    Certes Debian a 30 000 paquets, mais si un développeur KDE change l'ABI de kdelibs, ça va seulement et uniquement affecter les binaires KDE, que justement il allait mettre à jour. Je comprends que les changements d'ABI soient un problème dans les bibliothèques utilisées par un grand nombre de projets. Mais pour les libs KDE utilisées exclusivement par les logiciels KDE (bon ça peut changer avec la modularisation de KF5 mais on n'est pas encore arrivés là) je ne comprends pas.

    • [^] # Re: Quelqu'un peut-il m'expliquer le problème avec l'ABI de KDE

      Posté par  . Évalué à 9.

      (bon ça peut changer avec la modularisation de KF5 mais on n'est pas encore arrivés là) je ne comprends pas.

      Pourtant Amarok, Digikam, Plasma (pour le moment) ou encore Calligra ont des cycles de release distinct des release des "Software Compilation", ça fait déjà quelques logiciels pour lesquels il faut vérifier cette compatibilité.

      « Rappelez-vous toujours que si la Gestapo avait les moyens de vous faire parler, les politiciens ont, eux, les moyens de vous faire taire. » Coluche

    • [^] # Re: Quelqu'un peut-il m'expliquer le problème avec l'ABI de KDE

      Posté par  (site web personnel) . Évalué à 4.

      Je n'ai peut-être pas bien compris, mais il y a plusieurs cas :
      - que se passe-t-il quand tu ne mets que partiellement à jour ?
      - le problème des versions nécessaires pour que l'ensemble des logiciels installés fonctionne.
      - une librairie qui change d'ABI et demande de reconstruire et tester tout ce qui dépend d'elle. C'est normal mais pas très productif et ça prend du temps, ce qui est le thème de l'article de Riddell.

      "La liberté est à l'homme ce que les ailes sont à l'oiseau" Jean-Pierre Rosnay

    • [^] # Re: Quelqu'un peut-il m'expliquer le problème avec l'ABI de KDE

      Posté par  . Évalué à 5.

      Un exemple, si tu prends calligra :
      https://packages.qa.debian.org/c/calligra.html

      En ce moment, il est dans les transitions des bibliothèques librevenge, libwpd, libwpg, libicu, libwps, libexiv2-13, libexiv2, libilmbase et libvisio.

      Est-ce que ces mises à jour de bibliothèque vont tout casser ??

      C'est pareil pour les bibliothèques KDE, certaines sont assez utilisées dans et en dehors de KDE.

    • [^] # Re: Quelqu'un peut-il m'expliquer le problème avec l'ABI de KDE

      Posté par  (site web personnel) . Évalué à 10. Dernière modification le 18 août 2014 à 08:22.

      il faut recompiler KDE certes, mais c'était justement ce qu'il allait faire pour mettre à jour KDE, donc quel est le problème ?

      le problème de base, c'est pas KDE mais le fait que l'ABI en C++ est complètement casse gueule (Et je suis dev C++).

      • Le moindre ajout / modification de fonction "virtual" pète l'ABI
      • Le moindre ajout / modification/ suppression de data-member, même privé, change la taille de la class donc pète l'ABI.
      • Le moindre changement dans les signatures, comme un changement de "int" à "unsigned int" pour une fonction change le name mangling, donc pète l'ABI.

      En C++, les devs qui arrivent à maintenir une compatibilité binaires parfaite entre version (comme Qt) se rapprochent plus du statuts de Dieu vivant que de développeur.

      Pour reprendre ta phrase, oui c'est un GROS problème de devoir recompiler toute la stack à chaque changement dans une bibliothèque.
      1- Une lib dont l'ABI casse tous les trois jours est une lib inutilisable dans un soft non packagé dans les dépots officiels.

      2- L’intérêt principal des bibliothèque partagées est justement de pouvoir patcher les différents modules de manière indépendante … ( Ou autrement dit, ne pas recompiler 20k package chaque semaine à cause d'un bug fix openSSL )

      La solution au problème, serait qu'une bande de dudes se décide une bonne fois pour toute de définir une ABI C++ un peu plus saine d'esprit. Une qui ne vous force pas à utiliser des patterns Pimpl et des fonctions pointers toutes les 3 lignes.

      • [^] # Re: Quelqu'un peut-il m'expliquer le problème avec l'ABI de KDE

        Posté par  . Évalué à 4.

        Alors il s'agit plus de définir une ABI compatible entre les différents "vendors",
        mais du moins ça a été discuté dans le C++ Committee Meeting de juin 2014 :

        Je vous laisse regarder un peu, pas eu le temps de survoler pour un petit résumé.

        Ce qui est déjà un grand pas, l'ABI C++ a tendance à jouer la danse de la saint Guy dès qu'un bout de son environnement change (msvc, je te regardes).

        A voir s'ils vont réussir à se mettre d'accord, que le respect du standard tienne ;
        et peut être par effet de bord on aura une petite facilité à maintenant une ABI entre chaque changement de code.

        • [^] # Re: Quelqu'un peut-il m'expliquer le problème avec l'ABI de KDE

          Posté par  (site web personnel) . Évalué à 5. Dernière modification le 18 août 2014 à 13:09.

          Alors il s'agit plus de définir une ABI compatible entre les différents "vendors",
          mais du moins ça a été discuté dans le C++ Committee Meeting de juin 2014

          C'est un bon pas en avant, mais ça ne corrige malheureusement pas le problème.

          Ce qu'ils essaient de corriger est principalement les problèmes de compatibilités entre les binaires des différents compilateurs. Ce qui est au passage un autre cauchemar du C++. L'inlining / le mangling changeant au grés des versions, il n'est pas rare qu'une bibliothèque compilée avec GCC et utilisée avec clang… ne plus link plus proprement à la prochaine version de GCC (et je ne parle même pas de MSVC ahah )

          Les principaux problèmes d'ABI causant des mots de têtes aux packagers sont assez différents.

          L'un vient du fait que la taille des types est décidée à la compilation en C++. Ce qui signifie que modifier un data membre d'une class publique sans utiliser le pattern Pimpl/d_ptr est une catastrophe. Une solution à ça pourrait être le proposal N4025 si défini proprement.

          L'autre vient de la vtable. Le polymorhisme en C++ est implémenté via un vtable, ce qui est excellent en terme de performance mais à chier en terme de maintenabilité.
          La seul solution que je vois à ce problème serait la définition d'un type "Super-class" qui substitue la vtable pour un système un peu plus sain en terme de maintenabilité.

          • [^] # Re: Quelqu'un peut-il m'expliquer le problème avec l'ABI de KDE

            Posté par  . Évalué à 1.

            Les principaux problèmes d'ABI causant des mots de têtes aux packagers sont assez différents.

            L'un vient du fait que la taille des types est décidée à la compilation en C++.

            Je me demande si les librairies compilées ne posent pas plus de problème qu'ils en résolvent et si un système à la ANDF ne serait pas intéressant..

            Et puis ça permettrait potentiellement de "reconfigurer la librairie" en fonction de l'application: une application qui a un gros besoin de performance? Un int C reste un entier avec débordement silencieux, autrement un int devient un entier 'vérifié' qui arrête l'application en cas de débordement (sémantique autorisée par le C/C++).

            Pour l'utilisation de vtable et d'un vrai "appel par message" en plus, je trouve ta suggestion intéressante après tout c'est juste l'API externe qui nécessite d'être déclarée ainsi (si on veut maximiser les perf) et bien délimiter/définir l'API externe est une bonne idée je pense.
            Dans le même genre, j'ai toujours trouver dommage qu'en C++ les méthodes étaient publique par défaut au lieu de privée.

          • [^] # L'avis de Bjarne Stroustrup

            Posté par  . Évalué à 2. Dernière modification le 20 août 2014 à 19:27.

            il n'est pas rare qu'une bibliothèque compilée avec GCC et utilisée avec clang… ne plus link plus proprement à la prochaine version de GCC (et je ne parle même pas de MSVC ahah )

            Une interview juste publiée sur Slashdot contient justement l'avis de Bjarne Stroustrup sur la question de l'ABI. Je ne peux pas traduire en entier (pas sous licence libre), les principaux points de la réponse de Bjarne sont :

            1. Les communautés de chaque compilateur ne veulent pas perdre leur compatibilité avec les versions antérieures, il serait donc difficile de faire changer l'ABI de chaque compilateur dans un sens de meilleure compatibilité. Au mieux on pourrait faire en sorte que les compilateurs proposent une deuxième ABI en option.

            2. Pour être utile l'ABI commune devrait couvrir l'ensemble de la STL et c'est un problème très complexe.

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.