Partage
  • Partager sur Facebook
  • Partager sur Twitter

Erreur avec vecteur de pointeurs

    5 décembre 2019 à 16:27:00

    Bonjour :)

    J'ai comme un petit problème avec mon code, mais je n'arrive pas à voir d'où vient le problème.

    Je veux surcharger le constructeur par copie pour gérer la copie de pointeurs mais après exécution de ce constructeur mon programme plante.

    Voici mon code :

    EDT::EDT(EDT const& edt)
    {
        Enseignement* ptr;
        for (unsigned int i(0); i<edt._liste.size(); ++i)
        {
            ptr = edt._liste[i];
            _liste.push_back(ptr);
        }
        ptr = nullptr;
    }

    Ma classe EDT :

    class EDT
    {
    public:
        EDT() = default;
        EDT(EDT const& edt); // Constructeur par copie
        virtual ~EDT();
    
        //Méthodes .....
    
    private:
        std::vector<Enseignement*> _liste;
    };

    Si quelqu'un peut m'éclairer là dessus je lui serait reconnaissant. Merci !

    • Partager sur Facebook
    • Partager sur Twitter
      5 décembre 2019 à 17:18:08

      Bonjour,

      Pour copier un std::vector il y a bien plus simple:

      EDT::EDT(EDT const& edt) : _liste(edt._liste)
      {
      }

      Le 'égal' marche très bien! Et revient à faire exactement ce que tu as écrit!
      Si tu as un problème ça doit être dans ce que tu présentes derrière le Enseignement*. Tu sembles gérer de la mémoire dynamique directement, ce qu'il ne faut normalement jamais faire!

      • Partager sur Facebook
      • Partager sur Twitter

      En recherche d'emploi.

        5 décembre 2019 à 17:23:24

        Je n'ai pas pris l'option de la simple assignation parce que je n'ai pas envie que mes nouveaux pointeurs pointent juste vers le même objet que mon vector de base.

        Ma classe Enseignement est abstraite, et mon vector simplement constitué de pointeurs vers des Enseignements, je ne vois pas où est le problème :(

        • Partager sur Facebook
        • Partager sur Twitter
          5 décembre 2019 à 17:53:59

          >je ne vois pas où est le problème :(

          Entre la chaise et le clavier. ;)

          Tu te prends la tête pour rien et des personnes, plus expérimenté que toi à première vue, ont fait en sorte que l'opérateur égal fonctionne correctement (quand on suit les best practices, dont ne pas gérer la mémoire à la main).

          Tu utilises des pointeurs nus et du n'est pas "aware" sur le concept d'ownership, ça sent pas bon.

          Je pense que vous devriez revoir l'ownership et les pointeurs intelligents avant de vous faire péter un anévrisme au cerveau, pour rien.

          • Partager sur Facebook
          • Partager sur Twitter
          Je recherche un CDI/CDD/mission freelance comme Architecte Logiciel/ Expert Technique sur technologies Microsoft.
            5 décembre 2019 à 18:06:17

            ncRakl a écrit:

            Je n'ai pas pris l'option de la simple assignation parce que je n'ai pas envie que mes nouveaux pointeurs pointent juste vers le même objet que mon vector de base.

            Ce que tu fais revient à copier tous les éléments du vecteurs donc est totalement identique à copier directement le vecteur.
            Tu ne veux pas que les pointeurs pointent au même endroit donc tu considères que c'est toi qui gère les allocations dynamiques et donc c'est à toi de ne pas copier directement pointeurs; mais il faut faire une allocation qui sera la copie et mémoriser ce nouveau pointeur. Il ne faut normalement jamais gérer cela directement car il existe des tas de moyens beaucoup plus sûr.

            Ce que tu veux (mais si un de mes élèves fait ça il se fait taper sur les doigts) :

            EDT::EDT( EDT const& edt ) {
                for ( Enseignement* x : edt ) {
                    _liste.push_back( new Enseignement(*x) );
                }
            } // J'ai dû supposer que Enseignement* représente un pointeur alloué par new et que l'objet Enseignement est copiable

            ncRakl a écrit:

            Ma classe Enseignement est abstraite, et mon vector simplement constitué de pointeurs vers des Enseignements, je ne vois pas où est le problème :(

            Vois-tu maintenant le problème? Quand on écrit Enseignement*, il n’apparaît aucune information sur la manière d'allouer et copier les Enseignements. A toi d'y penser partout. Exemple de code qui pose un problème :

            EDT  edt1;
            EDT  edt2;
            // ... ... ... remplir edt1 ... ... ...
            edt2 = edt1; // => problème car on ne passe pas par le constructeur de copie


            • Partager sur Facebook
            • Partager sur Twitter

            En recherche d'emploi.

              6 décembre 2019 à 10:32:06

              • Pourquoi est-ce que Enseignement est stocké sous forme de pointeur brut ? S'il est propriétaire de la mémoire c'est qu'il y a un problème
              • Sauf cas de force majeur et si Enseignement est un objet polymorphe il ne devrait pas être copiable car c'est une entité
              • Si ce n'est pas un objet polymorphe il suffit de le stocker sous forme de variable simple, pas de smart-pointeurs nécessaire (et les copies/déplacements seront automatiques).
              • Partager sur Facebook
              • Partager sur Twitter

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

                6 décembre 2019 à 10:37:39

                Salut,

                En effet, un objet polymorphe n'a normalement pas vocation à être copié.

                Si tu ne veux pas t'emmerder, utilise des std::shared_ptr 

                std::shared_ptr<UnObjetPolymorphe>

                Ainsi quand tu veux recopier un objet qui contient un objet ou un tableau d'objets polymorphes ça se copie tout seul, (tout en pointant sur le même), ça se désalloue tout bien, ça fait la sauce correctement au niveau de la mémoire, ça se manipule simplement.

                • Partager sur Facebook
                • Partager sur Twitter

                Recueil de code C et C++  http://fvirtman.free.fr/recueil/index.html

                  6 décembre 2019 à 10:39:47

                  Peut-être ce n'est pas ce dont souhaite l'auteur. Le shared_ptr copié pointe toujours sur le même objet. Si le but est de faire une copie profonde le problème est toujours là.
                  • Partager sur Facebook
                  • Partager sur Twitter

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

                    6 décembre 2019 à 10:41:23

                    Il y a probablement un problème de conception en amont.
                    • Partager sur Facebook
                    • Partager sur Twitter

                    Recueil de code C et C++  http://fvirtman.free.fr/recueil/index.html

                      6 décembre 2019 à 18:07:44

                      Salut,

                      ncRakl a écrit:

                      Ma classe Enseignement est abstraite,

                      Oh, STOP!!!!

                      Dés le moment où tu as écrit cette phrase, tu as scellé ton destin: Ta classe Enseignement  est une classe qui a sémantique d'entité.

                      Cela signifie qu'elle ne peut EN AUCUN CAS être copiée.  Il n'y a pas à aller plus loin!!! Parce que tu ne veux en aucun cas risquer de te retrouver, à un moment donné de l'exécution, avec deux instances représentant de l'enseignement XXX qui auraient évolué différemment.

                      (C'est ce que Fvirtman a dit deux interventions plus haut, je me contente d'expliquer de manière plus explicite ;) )

                      A partir de là, il faut que tu fasse une distinction très claire entre les éléments qui ne font que manipuler tes enseignements (mais qui ne peuvent décider ni d'en créer de nouveau, ni de détruire les existants), et ce qui va prendre la responsabilité spécifique de les maintenir en mémoire "aussi longtemps que nécessaire.

                      S'il n'y a qu'un seul élément qui prend en charge la création, le maintient en mémoire et la destruction des différentes instance de la classe Enseignement, tu as -- très largement -- intérêt à utiliser les std::unique_ptr (*), et à veiller à les transmettre (aux éléments qui ne font que les manipuler) sous la forme de référence, voir, sous forme de référence constantes, si celui qui les manipule ne cherche pas à les modiier.

                      Dans de rares cas, plusieurs éléments doivent agir "d'un commun accord" pour assurer l'existence des différentes instances de Enseignements.  On peut alors éventuellement envisager le fait de les maintenir en mémoire sous forme de std::shared_ptr.  Mais cette solution ne devrait être utilisée qu'en tout dernier recours ;)

                      Fvirtman a écrit:

                      Il y a probablement un problème de conception en amont.

                      C'est même bien plus que "probablement": Il y a clairement un problème de conception

                      markand a écrit:

                      Peut-être ce n'est pas ce dont souhaite l'auteur. Le shared_ptr copié pointe toujours sur le même objet. Si le but est de faire une copie profonde le problème est toujours là.

                      Dis toi bien que ce que souhaite l'auteur n'a plus la moindre importance, vu qu'il se trouve face à une incohérence majeure: il essaye d'utiliser une classe ayant sémantique d'entité comme si elle avait en réalité sémantique de valeur.

                      C'est comme si tu voulais avoir de la glace bouillante ou de la lave (encore liquide, mais) gelée. Les deux concepts sont à se point incompatibles qu'il n'y a pas d'autre solution que de revoir sa copie ;)

                      On a beau être gentil et tout ce que l'on veut, il nous est impossible de tergiverser sur ce point ;)

                      -
                      Edité par koala01 6 décembre 2019 à 18:08:42

                      • Partager sur Facebook
                      • Partager sur Twitter
                      Ce qui se conçoit bien s'énonce clairement. Et les mots pour le dire viennent aisément.Mon nouveau livre : Coder efficacement - Bonnes pratiques et erreurs  à éviter (en C++)Avant de faire ce que tu ne pourras défaire, penses à tout ce que tu ne pourras plus faire une fois que tu l'auras fait

                      Erreur avec vecteur de pointeurs

                      × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                      × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                      • Editeur
                      • Markdown