nazcafan a écrit 175 commentaires

  • # problème A -> B

    Posté par . En réponse au message Le constructeur d'une classe de base peut-il savoir qu'il n'est pas le dernier?. Évalué à 2.

    Je pense que ce que tu cherches à faire est impossible, et j'ai l'intuition que le vecteur dont la taille change selon la classe est une mauvaise solution B à un problème A que j'aimerais bien connaître.

  • [^] # Re: quelques éléments de réponse

    Posté par . En réponse au message classe C++, membre structure C et allocation dynamique. Évalué à 5.

    Dans quel cas faut-il implémenter un deleter pour un unique_ptr ? Notamment si je dois nettoyer la structure pointée avant qu'elle soit libérée ? Le deleter par défaut est appelé par le destructeur de MaClasse ?

    Le deleter par défaut est appelé par le destructeur de unique_ptr après que le destructeur de ta classe a fini de s'exécuter (cf ma première réponse). En l’occurrence, tu pourrais le remplacer par un Deleter qui appelle la fonction de nettoyage C avant de libérer la mémoire :

    #include <memory>
    #include <iostream>
    #include <exception>
    
    extern "C"
    {
    struct my_c_struct {int data;};
    int s_init(my_c_struct * c){ std::cout << "C initializing\n"; return 1;}
    void s_destroy(my_c_struct *c){ std::cout << "C clean up\n";}
    }
    
    class MyClass
    {
    public:
      MyClass();
    private:
      struct Deleter
      {
          void operator()(my_c_struct * p)
          {
              s_destroy(p);
              delete p;
          }
      };
      std::unique_ptr<my_c_struct, Deleter> s; 
    };
    
    MyClass::MyClass()
    : s(new my_c_struct)
    {
        int rc = s_init(s.get());
        if (rc != 0)
        {
            throw std::runtime_error("could not initialize c_struct, rc = " + std::to_string(rc));
        }
    }
    
    int main()
    {
        try
        {
            MyClass m;
            // allocation s'est bien passée, je peux continuer ?
        }
        catch (std::exception const& e)
        {
            std::cout << "runtime error: " << e.what() << '\n';
            return 42;
        }
        return 0;
    }

    C'est une approche un peu bâtarde à mon goût parce que les responsabilités d'initialisation et de de nettoyage C ne sont pas du ressort du même objet : l'initialisation est faite dans le constructeur de MyClass et le nettoyage dans le Deleter du unique_ptr. Du point de vue ingénierie, ce n'est pas particulièrement idéal, d'ailleurs tu noteras que le code de nettoyage C est lancé même si l'initialisation échoue. Ça dépend probablement de ton API C, mais en général, c'est inutile, voire dangereux. Pour le coup, il serait peut-être préférable de laisser la responsabilité de gérer la mémoire au unique_ptr et de laisser à ta classe de gérer l'initialisation / nettoyage :

    #include <memory>
    #include <iostream>
    #include <exception>
    
    extern "C"
    {
    struct my_c_struct {int data;};
    int s_init(my_c_struct * c){ std::cout << "C initializing\n"; return 1;}
    void s_destroy(my_c_struct *c){ std::cout << "C clean up\n";}
    }
    
    class MyClass
    {
    public:
      MyClass();
      ~MyClass();
    private:
      std::unique_ptr<my_c_struct> s; 
    };
    
    MyClass::MyClass()
    : s(new my_c_struct)
    {
        int rc = s_init(s.get());
        if (rc != 0)
        {
            throw std::runtime_error("could not initialize c_struct, rc = " + std::to_string(rc));
        }
    }
    
    MyClass::~MyClass()
    {
        s_destroy(s.get());
    }
    
    int main()
    {
        try
        {
            MyClass m;
            // allocation s'est bien passée, je peux continuer ?
        }
        catch (std::exception const& e)
        {
            std::cout << "runtime error: " << e.what() << '\n';
            return 42;
        }
        return 0;
    }

    Ici, le code de nettoyage C n'est appelé que si l'initialisation C a abouti.

    / et je gère le fait que l'allocation s'est mal passée ?

    Le catch va récupérer toutes les erreurs, notamment les erreurs d'allocation, et l'exception due à une mauvaise initialisation en C. Mais au moins toutes les ressources auront déjà été libérées au moment du catch, en gros, à ce niveau tu n'as plus qu'à logguer, tout l reste est déjà « géré ». Le fait de confier la libération des ressources aux destructeurs des objets te permet d'avoir une logique try - catch relativement simple comparé à d'autres langages.

  • [^] # Re: quelques éléments de réponse

    Posté par . En réponse au message classe C++, membre structure C et allocation dynamique. Évalué à 2.

    Cela m'intéresse aussi, mais, hum, ça sera pour la deuxième semaine. Comment utiliser un unique_ptr si je dois passer ce pointeur à une fonction C qui le modifie (ou qui modifie la valeur de certains membres de la structure pointée) ?

    Tu peux utiliser unique_ptr::get :

    #include <memory>
    #include <iostream>
    
    struct Blah
    {
        int value;
    };
    
    int main()
    {
       std::unique_ptr<Blah> unique{new Blah()};//zero-initialization
       std::cout << unique->value << '\n';//0
       Blah * ptr = unique.get();
       ptr->value = 42;
       std::cout << unique->value << '\n';//42
    }
  • [^] # Re: quelques éléments de réponse

    Posté par . En réponse au message classe C++, membre structure C et allocation dynamique. Évalué à 3. Dernière modification le 22/04/17 à 00:47.

    Ben, c'était mon plan de départ, mais j'ai cru comprendre (peut-être par erreur) que le lancement d'une exception dans un constructeur laisse la construction de l'objet inachevée, et que donc son destructeur n'est pas appelé au moment opportun. Si j'avais déjà alloué des trucs au moment du lancement de l'exception, il faut que je fasse le ménage avant de lancer l'exception ?

    C'est une question pertinente. Ce que tu décris est juste, mais une nuance t'échappe. Effectivement, si le constructeur d'un objet émet une exception, l'objet n'est pas considéré comme construit et son destructeur n'est pas appelé. Toutefois, le destructeur des membres et le destructeur des classes de base sont appelés.
    Ce qui m'amène à une réponse plus complète : effectivement, si une exception est lancée depuis le constructeur au milieu de l'allocation de différentes ressources, les libérer proprement risque d'être particulièrement ardu. En conséquence, il est fortement déconseillé pour une classe C++ de gérer directement plus d'une seule ressource. Les autres ressources doivent être gérées par des membres ou des classes de base, dont le destructeur (et donc la libération de la ressource) sera appelé automatiquement par le langage, même dans le cas où l'exception est lancée dans le constructeur.

  • # quelques éléments de réponse

    Posté par . En réponse au message classe C++, membre structure C et allocation dynamique. Évalué à 4. Dernière modification le 21/04/17 à 17:15.

    • En ce qui concerne new VS malloc pour allouer une struct C, je n'ai pas vraiment d'avis ; tant que tu les utilises correctement, ça na va pas changer l'univers. new peut utiliser un autre allocateur que malloc mais tant que tu ne mélanges pas malloc/free avec new/delete sur le même objet, ça ira.
    • La spécification C++ dit que si new échoue à allouer de la mémoire, il émet une exception de type std::bad_alloc, du coup, il est inutile de tester le pointeur de retour envers nullptr.
    • Personnellement, je décourage l'utilisation d'une fonction public du genre init(). Ça laisse plus d'opportunités à l'utilisateur de la classe de se tirer une balle dans le pied. Je suis partisan d'insérer le code d'init dans le constructeur et de balancer une exception en cas d'erreur. Au moins l'utilisateur ne se retrouvera jamais avec un objet inutilisable.
    • si tu as testé le pointeur à la construction, le tester à la destruction est excessif.
    • tu peux probablement déléguer la gestion de ton pointeur à un pointeur intelligent tel que unique_ptr, en définissant le Deleter idoine.
  • # question innocente…

    Posté par . En réponse au journal Java dans le navigateur : ce n'est pas fini, ça sera pire !. Évalué à 8.

    Est-ce que ça peut faire tourner Rhino ?

  • # Ambiance

    Posté par . En réponse au journal Faut tout faire soi-même !. Évalué à 10.

    Je travaille à Londres et l'ambiance est plutôt morose, ici. La plupart des gens sont conscients de combien l'Europe a apporté depuis une vingtaine d'années. En Angleterre, le vote "Leave" semble avoir gagné surtout en Province (excepté quelques grandes villes). Peut-être que les richesses que la capitale a amassées n'ont pas été distribuées suffisamment équitablement et que les Anglais l'ont fait savoir à leurs dirigeants.

    Les temps qui arrivent s'annoncent tumultueux, certains parlent déjà d'un second referendum, mais je ne vois pas trop comment le prochain premier ministre (Boris Johnson semble pressenti) pourra ou voudra décemment proposer ça.

    De maniérè plus générale, j'ai peur du précédent que ça a créé… J'ai l'impression que si les défauts majeurs que les dernières crises on révélé dans l'UE (déficit démocratique avec une commission encore trop puissante, mauvaise intégration des économies plus "faibles" dans la monnaie unique, et une gestion inhumaine et calamiteuse de la question des migrants et des frontières extérieures), alors elle est condamnée a se déliter au cours des prochaines années.

  • [^] # Re: peut-être ceci ?

    Posté par . En réponse au message Petit soucis avec les shared_ptr. Évalué à 2.

    Mec, le but des shared_ptr, unique_ptr et autres est d'implanter une notion de propriété (ownership) qui, en gros représente la responsabilité de détruire l'objet et libérer la mémoire sur laquelle il a été construit.
    Si l'objet est global ou qu'il est alloué sur la pile, il est détruit automatiquement quand le programme s’arrête ou quand le programme quitte le scope dans lequel il a été déclaré. En conséquence, il n'y a aucun intérêt à créer un pointeur intelligent dessus.

    Si tes objets sont placés dans un graphe, cette responsabilité devrait revenir soit au graphe lui même, soit à des objets intermédiaires, par exemple les vector que tu utilises dans ton implantation. Su tu utilises un <vector<shared_ptr<T>>, les shared_ptr auront cette responsabilité, avec un effet de bord : tu pourras alors avoir détruit ton objet graphe et toujours avoir des T non-détruits si jamais tu as gardé des copies de shared_ptr. À toi de décider si c'est une bonne ou mauvaise chose .

  • [^] # Re: peut-être ceci ?

    Posté par . En réponse au message Petit soucis avec les shared_ptr. Évalué à 1. Dernière modification le 03/06/16 à 17:58.

    aussi, tu peux t'assurer facilement du fonctionnement de la mécanique de comptage en mettant p2 dans un scope :

      auto p1 = make_shared<MyInt>(MyInt::get(3));
    
      cout << "p1 : id = " << p1->get_id() << ", n_ptr = " << p1.use_count() << ", addr = " << p1.get() << endl;
      {
          auto p2 = p1;
    
          cout << "p1 : id = " << p1->get_id() << ", n_ptr = " << p1.use_count() << ", addr = " << p1.get() << endl;
          cout << "p2 : id = " << p2->get_id() << ", n_ptr = " << p2.use_count() << ", addr = " << p2.get() <<  endl;
      }
      cout << "p1 : id = " << p1->get_id() << ", n_ptr = " << p1.use_count() << ", addr = " << p1.get() << endl;

    résultat :

    Nb de MyInt : 5
    p1 : id = 3, n_ptr = 1, addr = 0x8289030
    p1 : id = 3, n_ptr = 2, addr = 0x8289030
    p2 : id = 3, n_ptr = 2, addr = 0x8289030
    p1 : id = 3, n_ptr = 1, addr = 0x8289030

  • # peut-être ceci ?

    Posté par . En réponse au message Petit soucis avec les shared_ptr. Évalué à 1.

    auto p1 = make_shared<MyInt>(MyInt::get(3));
    auto p2 = p1

    ça rend ça :

    Nb de MyInt : 5
    p1 : id = 3, n_ptr = 2, addr = 0x93e3030
    p2 : id = 3, n_ptr = 2, addr = 0x93e3030
    

    Comme il a été dit dans les commentaires précédents, make_shared va construire une copie de Myint::get(3), et initialiser un shared_ptr sur cette copie, pas sur le troisème élément de ton tableau.

  • [^] # Re: Franchement ...

    Posté par . En réponse au journal Linux passe devant MacOS sur le desktop. Évalué à 2.

    Trop gros, passera pas …

  • # LA grande leçon du bépo

    Posté par . En réponse au journal Le gouvernement français veut changer de clavier. Évalué à 4.

    S'il y a un truc à retenir, pour la complétion de leur clavier, c'est que le Alt-Gr + lettre main gauche, c'est extrêmement agréable et rapide à saisir, j'espère qu'ils s'en serviront à bon escient pour leur Azerty 2.0.

  • [^] # Re: niceness

    Posté par . En réponse au journal Les cgroups, un outil trop méconnu. Évalué à 3.

    It's nice to be important, but it's more important do be nice.

  • [^] # Re: HS emprunt immboilier

    Posté par . En réponse au journal MEGA c'est louche . Évalué à 1.

    Tout de même, la plupart des organismes de crédit te proposent de mettre en place un prélèvement automatique pour régler la facture, évitant ainsi des drames liés à l'étourderie naturelle des gens.
    Perso, j'ai pris ça, jamais eu de problème, ils envoient la facture suffisamment en amont du prélèvement pour que tu aies le temps de réagir si un truc pas catholique est arrivé avec ta carte.

  • [^] # Re: HS emprunt immboilier

    Posté par . En réponse au journal MEGA c'est louche . Évalué à 3.

    Une carte de crédit, c'est une facture à la fin du mois, et la possibilité de payer le solde ou un acompte minimum (la deuxième options génère des intérêts). Ils vont regarder ta capacité à rembourser « l'emprunt ».

    de mémoire pour le crédit score au Royaume Uni ils regardent :

    • compte courant
    • factures d'électricité / gaz
    • factures téléphone mobile
    • cartes de crédit
    • prêt immobilier
    • inscription sur les listes électorales (va comprendre)

    Il est à noter que les comptes récemment ouverts jouent négativement sur le credit score, mais au bout de 3 mois où tu payes rubis sur l'ongle, ça compte positivement (6 mois pour le crédit immobilier). Autrement dit, le jour où tu prends un crédit immobilier et que tu déménages (création de 3 comptes: crédit immobilier + gaz + électricité + plus inscrit sur la liste électorale si t'as changé de circonscription), c'est même pas la peine de songer à prendre une carte de crédit pendant 6 mois.

  • [^] # Re: Frais bancaires

    Posté par . En réponse au journal MEGA c'est louche . Évalué à 1.

    De plus en plus de companies proposent des transferts à des prix plus avantageux que ce que font les banques, mes collègues me parlent souvent de Transferwise. Je n'ai pas utilisé personnellement, mais ils ont l'air content.

  • [^] # Re: Qu'est-ce qui ne va pas avec le virement bancaire?

    Posté par . En réponse au journal MEGA c'est louche . Évalué à 3.

    Résidant au Royaume Uni, je peux t'affirmer que les cartes de paiement à débit immédiat (debit card) y sont très répandues, même si beaucoup de gens ont une carte de crédit en sus (le plus souvent pour avoir un bon « credit score » le jour où ils prendront un emprunt immobilier). Donc non, la carte de débit n'est certainement pas une spécificité française.

  • # quel intérêt ?

    Posté par . En réponse au journal Bépo sous Android. Évalué à 9. Dernière modification le 16/06/15 à 16:48.

    Sachant que le bépo est quand même conçu et optimisé pour la saisie à dix doigts, quel est l'intérêt d'en faire une variante pour clavier virtuel swipe (perso, sur mon android, j'utilise juste un pouce) ? Même le « œ » est présent parmi les options de la touche « o » sur le clavier azerty Android de base.

  • # Mali

    Posté par . En réponse au journal Carte à base d'ARM 4 coeurs au prix d'un Raspberry pi.. Évalué à 10.

    J'avais acheté une carte avec un chipset graphique mali il y a un an en me disant que le project LIMA libre était bien avancé, mais depuis rien … Je crois que le développeur a été dégouté/menacé par ARM qui visiblement voit ce projet de façon assez hostile. En gros, si tu comptes avoir des pilotes libres en mainline pour ta carte, il va probablement falloir écrire tout ça toi-même.

    En comparaison, à la même époque le RPI avait plein de blobs proprios en userspace et les projets de pilotes graphiques libres étaient embryonnaires, mais depuis ils ont tout [référence nécessaire] libéré, probablement parce que la fondation derrière le RPI a poussé le constructeur au cul… Pas de bol pour moi, j'ai peut-être joué le mauvais cheval ;-)

    Ceci dit, à 40 $, tu prends pas un gros risque non plus, hein…

  • # j'ai vu bien pire

    Posté par . En réponse au journal Veuillez instancier ce journal avant de le lire. Évalué à 8. Dernière modification le 09/10/14 à 18:50.

    Le code est plutôt clair est lisible (j'aime pas les #pragma, mais je suis old-school), je ne me suis pas penché sur le design, quelques remarques/questions en vitesse :

    • dans framerate.cpp :
    ...
     if (current_ticks - last_frame_ticks >= max_frame_ticks) {
      max_ticks = current_ticks - last_frame_ticks;
    }
    ...

    utiliser std::max ?

    • Je vois que tu utilises souvent des shared_ptr, je n'ai pas encore bien regardé le besoin à haut niveau, mais parfois, les unique_ptr font l'affaire et te coûteront probablement moins cher ;

    • Sinon, évite d'utiliser std::endl, '\n' est ce que tu veux utiliser dans 99% des cas (dans ton cas, c'est juste dans le main(), donc ça changera rien mais mieux vaut prendre des bonnes habitudes) ;

    • Dans assets.cpp, tu dois pouvoir initialiser pathPrefixes_ à l'aide d'une intializer list, ça t'évite d'avoir à ré-allouer. (pareil qu'avant : dans ce contexte c'est du chipotage, mais il s'agit de prendre le pli).

    Si j'ai du temps et que je m'ennuie, j'essaierai de prendre du recul et voir comment tout ce tient.

  • # Même galère

    Posté par . En réponse au journal Libre office, ça suçe des ours en Alaska.. Évalué à 1.

    J'ai essuyé des déboires similaires pour le publipostage depuis une base de données il y a quelques années. Le publipostage intégré dans Access faisait correctement le travail, mais le composant Base de libre office sous-traitait le travail à Writer, et visiblement, ça rendait l'exercice difficile sinon périlleux.

    J'ai essayé pendant un moment. C'était faisable, mais vraiment pénible, par rapport au truc sous Access. Du coup j'ai fini par faire acheter une licence Access à l'utilisateur.

    Je pense que le composant Writer a été bien travaillé, mais que les autres ont encore des progrès à faire pour convenir à certains usages un peu avancés qu'on peut trouver parmi les utilisateurs de la bureautique, ceci étant, il faut bien commencer quelque part et c'est normal que la priorité ait été mise sur Writer, non ?

  • [^] # Re: En entreprises…

    Posté par . En réponse au journal C++14. Évalué à 4.

    et mmmhhhh, la qualité a un coût, pas un coup, bon sang de bonsoir !

  • [^] # Re: En entreprises…

    Posté par . En réponse au journal C++14. Évalué à 5.

    Mouais, j'ai eu droit à cette rhétorique il y a quelques années. La boîte utilisait alors un gcc 3.4.6, et ils ne voyaient pas l'intérêt de mettre à jour.
    Un jour, j'ai écrit un truc du genre:

    int * a = new int[LENGTH]();

    j'ai mis un moment avant de comprendre que mon code déconnait sévère parce que le compilo refusait d'initialiser les valeurs à zéro, et encore un moment pour comprendre que je pouvais me brosser pour avoir un correctif.

    Alors refuser les versions récentes sous prétexte que la qualité a un coup, OK, mais le risque est de se retrouver sur des versions obsolètes, non maintenues qui t'obligent à écrire des contournements qui n'ont pas lieu d'être.

    Je préfère un modèle de mise à jour régulière et progressive de la toolchain (on est pas obligé de toujours mettre du bleeding edge, hein), avec une procédure de validation bien définie, voire automatique. D'une part on le fait souvent, du coup on intègre des bonnes pratiques et ça évite d'avoir la « peur du changement ». D'autre part, le manque de qualité a également un coût, et sur le long terme, une boîte qui traine une grosse dette technique se fera ramasser par ses concurrentes, simplement parce qu'elle sera incapable de faire des changements importants dans un laps de temps raisonnable.

  • # mouais…

    Posté par . En réponse au journal C'est vendredi, c'est trolldi, c'est permis : l'open source n'est pas secure. Évalué à 10.

    En ce qui concerne openSSL, ce n'est pas parce que tout le monde a mis la tête dans le sable pendant des années que tu dois généraliser. Me semble que ce projet en particulier avait très peu de ressources et s'était enfermé dans un code et des pratiques qui rebutaient beaucoup de contributeurs potentiels.

    J'ai également l'impression d'ailleurs que Libre SSL attire un peu plus de monde, simplement parce qu'ils ont fait l'effort de faire le ménage et de regarder les rapports de bugs. Comme dit mon père (qui pourtant n'est pas un cador en informatique) : « le succès appelle le succès ».

  • # Cairo ?

    Posté par . En réponse au journal wlmessage, un équivalent à xmessage. Évalué à 2.

    Le choix de cairo s'est imposé naturellement pour ce que tu cherchais a faire ?

    C'est un portage de xmessage ou bien tu es reparti d'une page blanche sans trop regarder comment le truc de base était fait ?