Partage
  • Partager sur Facebook
  • Partager sur Twitter

Un destructeur fait planter

Mon programme recoit SIGTRAP.

Sujet résolu
    13 juin 2007 à 13:49:35

    Bonjour à tous,

    Mon problème vient d'un destructeur capricieux, je m'explique :
    Dans une méthode d'une classe je créer un objet d’une autre classe, je m’en sers puis je l’efface à la fin de ma méthode avec delete.

    void World::RegisterEntityType (const char* ETName)
    {
        EntityType *TempEntityType;
        TempEntityType = new EntityType(ETName);

        //La je fais ma sauce.

        delete TempEntityType;
    }


    Et voici donc le destructeur :

    EntityType::~EntityType ()
    {
        int i = 0;

        //Libération de la mémoire du nom
        if (cName != NULL)
            delete cName;

        //Libération de la mémoire des faces et des vertex
        if (!VectorFace.empty ())
            for (i = 0; i < VectorFace.size(); i++)
                delete VectorFace.at (i);

        if (!VectorVertex.empty ())
            for (i = 0; i < VectorVertex.size(); i++)
                delete VectorVertex.at (i);
    }


    J’ai constaté plusieurs choses :
    -En ne laissant que la declaration de l'entier il n'y a plus de problèmes.
    -Si je met un breakpoint dans le destructeur le programme n'y passe jamais.

    Je pense que le problème vient de par la mais si vous avez besoin de plus de code j'en mettrais.
    Merci d'avance pour vos réponses :)
    • Partager sur Facebook
    • Partager sur Twitter
      13 juin 2007 à 14:00:50

      On t'aiderait plus facilement si tu nous donnais la déclaration de ta classe ! Ce serait très pratique...
      • Partager sur Facebook
      • Partager sur Twitter
        13 juin 2007 à 14:22:05

        Voili voilou


        class EntityType
        {
            private:
            vector< Vertex* > VectorVertex;
            vector< Vertex* > VectorVT;//Coordonné texture - vertex
            vector< Face* > VectorFace;
            GLuint IDTexture;
            char* cName;

            public:
            EntityType (const char* _cName);//Constructeur
            EntityType (const EntityType &NewEntityType);//Constructeur de recopie
            ~EntityType ();//Destructeur


            //Reinitialise l'entité
            void reinitialize ();
            //Dessine l'entité
            void DrawEntityType ();
            //Recupere le nom
            char* GetName ();

            ////////////VERTEX////////////
            //Ajoute un vertex à la fin de la liste
            void AddVertex (Vertex *MyVertex);
            //Change le vector a sa taille final
            void FinalizeVectorVertex ();

            //////////FACE//////////////
            //Ajoute une face à la fin de la liste
            void AddFace (int idv1, int idv2, int idv3, int idvt1, int idvt2, int idvt3);
            //Change le vector a sa taille final
            void FinalizeVectorFace ();

            //////////VT //////////////
            //Ajoute un vt à la fin de la liste
            void AddVT (Vertex *MyVertex);
            //Change le vector a sa taille final
            void FinalizeVectorVT ();
        };


        Je te met l'implementation des constructeurs, si tu as besoin des autres méthodes je les mettrait.

        EntityType::EntityType (const char* _cName)
        {
            //La taille d'origine des vectors est de 150
            VectorVertex.reserve(150);
            VectorFace.reserve(150);

            //Affectation du nom
            if (_cName != NULL)
            {
                cName = new char[strlen(_cName)];
                strcpy (cName, _cName);
            }
        }


        EntityType::EntityType (const EntityType &NewEntityType)
        {
            //Recopi des vecteurs
            VectorVertex = NewEntityType.VectorVertex;
            VectorVT = NewEntityType.VectorVT;
            VectorFace = NewEntityType.VectorFace;
            //de la texture
            IDTexture = NewEntityType.IDTexture;
            //du nom
            cName = new char[strlen(NewEntityType.cName)];
            strcpy (cName, NewEntityType.cName);
        }


        Edit : Bon la je me sens con, en relisant mon post je me suis aperçu que j’avais un problème de conception au niveau du constructeur de recopie. Au niveau des vectors, j’affecte juste l’adresse sans réallouer de la mémoire pour le nouvelle objet …
        • Partager sur Facebook
        • Partager sur Twitter
          13 juin 2007 à 14:31:19

          Euh déjà, tu devrais savoir que les chaîne de caractères C se terminent par '\0' donc tu ne peux pas mettre simplement "new char[strlen(chaine)]" il faut que tu ajoutes un caractère qui n'est pas comptabilisé par strlen(). Ensuite, en C++, il vaut largement mieux utiliser le type : std::string pour les chaînes de caractères c'est beaucoup plus simple à gérer.
          • Partager sur Facebook
          • Partager sur Twitter
            13 juin 2007 à 16:18:31

            Des que j'aurait résolu ce problème, je remplacerai les char par des string. Sinon après avoir poussé mes recherches je me suis aperçu que le problème venait du constructeur d'une autre classe :

            class Face
            {
                private:
                int TabIndexVertex[2];//Contient les index des 3 vertex
                int TabIndexVT[2];//Contient les index des 3 coordonnées vertex - texture

                public:
                //Constructeur
                Face (int idv1, int idv2, int idv3, int idvt1, int idvt2, int idvt3);
                //Constructeur de copie
                Face (Face &MyNewFace);
                //Destructeur
                //~Face ();
                //Dessine la face
                void DrawFace(Vertex *v1, Vertex *v2, Vertex *v3, Vertex *vt1, Vertex *vt2, Vertex *vt3);
                //Accesseur des tableaux d'indexs
                int* GetTabIndexVertex () {return TabIndexVertex;}
                int* GetTabIndexVT () {return TabIndexVT;}
            };


            Cette classe ne possède pas de destructeur, et pourtant lorsqu'un objet de cette classe est détruit le compilateur s'arrête et me renvoie cette erreur :

            Program received signal SIGTRAP, Trace/breakpoint trap.
            In ntdll!DbgUiConnectToDbg () (ntdll.dll)

            Apres quelques recherche, j'ai trouver sur developpez quelqu'un disant que sigtrap est le signal envoyer par l'application lorsque qu'elle atteint un point d'arret. Mais je n'ai aucun point d'arret et encore moins à cette endroit.

            Et pour en venir au constructeur que voici :
            Face::Face (int idv1, int idv2, int idv3, int idvt1, int idvt2, int idvt3)
            {
                /*ATTENTION LES INDEX DANS LE VECTOR COMMENCENT A 0
                ALORS QU ILS COMMENCENT A 1 LORS DE LA DEFINITION DES FACES*/

                TabIndexVertex[0] = idv1-1;
                TabIndexVertex[1] = idv2-1;
                TabIndexVertex[2] = idv3-1;

                TabIndexVT[0] = idvt1-1;
                TabIndexVT[1] = idvt2-1;
                TabIndexVT[2] = idvt3-1;//Cette ligne creer le probleme
            }


            J’ai isolé le problème à une instruction en particulier, la dernières, si je l'enlève aucun problème ne se pose.
            • Partager sur Facebook
            • Partager sur Twitter
              13 juin 2007 à 18:50:09

              Pour commencer, je doute qu'il y ait besoin d'un destructeur car aucune variable de classe n'est allouée dynamiquement... À part ça, révise tes tableaux !
              Quant tu déclares un tableau comme ceci :

              int tab[2];

              les indices valides sont :

              tab[0] = 5;
              // et
              tab[1] = 6;

              Donc ton constructeur est faux ! Tu définis deux tableaux de 2 cases et tu alloues des valeurs comme si il s'agissait de tableaux de 3 cases !

              À part ça, je te conseille EXPRESSEMENT d'utiliser le type string SANS TARDER. Le type char* en C++ il faut l'oublier !
              • Partager sur Facebook
              • Partager sur Twitter
                13 juin 2007 à 19:30:48

                Se prendre la tète aussi longtemps sur un truc aussi bête ... je comptai bêtement 0, 1, 2 -> 3 élément, de toute façon maintenant que j'ai découvert les vectors et leurs facilités d'utilisation je croit que les tableaux vont passer à la trappe avec les char :)

                Merci pour votre aide, bye.
                • Partager sur Facebook
                • Partager sur Twitter
                  14 juin 2007 à 0:56:27

                  *

                  Citation : OP

                  void World::RegisterEntityType (const char* ETName)
                  {
                      EntityType *TempEntityType;
                      TempEntityType = new EntityType(ETName);

                      //La je fais ma sauce.

                      delete TempEntityType;
                  }

                  Dans cet exemple très précis, tu t'embêtes pour rien. Si ton TempEntityType ne doit pas sortir de la portée de cette fonction, mets là sur la pile.
                  void World::RegisterEntityType (const char* ETName)
                  {
                      EntityType TempEntityType(ETName);

                      // Là tu fais ta sauce.

                      // Là tu ne fais rien
                  }

                  Gains:
                  - rapidité
                  - sécurité (résistance aux exceptions)
                  - simplicité

                  NB: si l'entitytype pouvait être d'un type dérivé, c'est encore autrement qu'il faudrait s'y prendre.

                  * Pour le destructeur,
                  - inutile de tester si un pointeur est nul avant d'appeler delete (dans tous les cas il le fait)
                  - inutile de tester si vide puisque size() te renverra 0
                  => tes tests sont redondants

                  Dans les deux cas, cf la FAQ C++ de developpez (1- l'histoire du delete en plus de mots que moi, 2- comment libérer les pointeurs stockés dans un vecteur)


                  * Constructeur de copie incorrect + destructeur => plantages en perspectives
                  - tu as un problème de dangling pointer
                  - revoir le tuto de mathéo qui explique comment écrire des constructeurs de copie (à ce sujet, il a oublié l'opérateur d'affectation ; cf mes commentaires liés au tuto suivant, ou la FAQ C++ de developpez au sujet de l'écriture de l'opérateur d'affectation)

                  - dans tous les cas, je ne suis pas persuadé qu'il soit pertinent de copier des EntityType (rien que le nom déjà ...). Autant interdire ces 2 opérations.

                  • Partager sur Facebook
                  • Partager sur Twitter
                  C++: Blog|FAQ C++ dvpz|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS| Bons livres sur le C++| PS: Je ne réponds pas aux questions techniques par MP.

                  Un destructeur fait planter

                  × 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