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

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

XML Discussion :

Problèmes destructeurs + "arbre" de vecteurs


Sujet :

XML

  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    99
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 99
    Points : 303
    Points
    303
    Par défaut Problèmes destructeurs + "arbre" de vecteurs
    Bonjour!

    Ceci est mon tout premier message alors autant me présenter un peu: je suis étudiant en informatique pour les sciences, actuellement en stage de fin d'études. L'informatique pour les sciences est un master pour les personnes issuent d'autres filières scientifiques que l'informatique pure, on peut donc considérer que je suis débutant.

    L'université est très versée dans le Java, mais pour mon stage j'ai quand même dû apprendre le C/C++, vraiment sur le tas. Ce qui explique que je galère un peu.

    Voici mon problème:
    J'ai un arbre constitué de noeuds (classe Noeud). Les noeuds sont spécialisés à chaque étage: Arbre(racine) -> Type -> SousType -> Objet, tout ça pour coller au mieux à la structure du logiciel dont je programme une extension, tout en bénéficiant de la définition récursive de l'arbre.

    Chaque Noeud contient un pointeur vers le pere, et un vecteur de pointeurs vers les noeuds fils.
    La classe Objet est un peu particulière car elle contient un pointeur sur de la mémoire allouée par calloc. C'est une restriction imposée par l'API de l'hote.
    Pour stocker les pointeurs sur les fils (obtenus par "new ...") je suis obligé de les upcaster en Noeuds car le vecteur est déclaré comme un conteneur de Noeuds.

    L'arbre se construit sans mal, et j'ai même une belle sortie XML de mes données. Cependant, la destruction se passe très mal, faisant planter le greffon et l'hote.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    //creation de l'arbre:
    Arbre *ar= new Arbre(...); //les constructeurs s'appellent en cascade 
    //en même temps que les données de l'hôte sont parcourues
    //destruction de l'arbre:
    delete ar;
    J'ai tenté de me reposer sur les destructeurs par défaut, tout en soupçonnant que le calloc() poserait problème. Ca ne marche pas de toutes façons.
    J'ai donc envisagé un destructeur virtuel dans Noeuds

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    virtual ~Noeud()
    {
      for(int i = 0; i < numFils; i++)
      {
        delete fils[i]; // vector<Noeud*> fils;
      }
    }
    Mais ça ne marche pas mieux. J'ai soupçonné devoir downcaster mes Noeud* (ceux du vecteur) dans leurs types réels pour pouvoir les supprimer. J'ai pas trouvé d'autre moyen que de déplacer le code ci-dessus dans les classes dérivées (c'est pas avantageux). Pour la classe Arbre ça donne:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    ~Arbre()
    {
    	//fputs("Execution destructeur Arbre\n", debug);
    	for(int i = 0; i < numFils; i++)
    	{
    		delete (Type*)fils[i];
    	}
    	system("pause"); //pour contrôler où en est le code
    }
    ça ça se passe bien, j'ai une invite de commande qui apparait me demandant de presser une touche pour continuer, mais après avoir pressé une touche ça crashe! Il n'y même pas d'appel du destructeur ~Noeud!

    Je suis coincé! Je ne vois plus par quel bout attaquer le problème! Ce qui devait être une tâche à priori triviale (a vue de nez), s'avère être un gros calvaire:
    -ma mémoire ne se libère pas!
    -si j'enlève la commande "delete ar;" ça ne plante plus, mais une seconde execution fait planter l'hote, normal.
    -j'ai déjà trop passé de temps sur ce problème!

    Ma question est donc, sachant tout cela: quel est le moyen qui convient le mieux pour libérer la mémoire allouée à cet arbre?

    J'espère que vous pourrez m'aider!

    merci!
    mango

  2. #2
    Membre du Club
    Inscrit en
    Avril 2007
    Messages
    46
    Détails du profil
    Informations forums :
    Inscription : Avril 2007
    Messages : 46
    Points : 47
    Points
    47
    Par défaut
    Bonjour,

    Quel IDE utilises-tu? n'as-tu pas la possibilité de savoir exactement où ça plante? Est-ce que Arbre est une classe fille?

  3. #3
    Rédacteur

    Avatar de Matthieu Brucher
    Profil pro
    Développeur HPC
    Inscrit en
    Juillet 2005
    Messages
    9 810
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Développeur HPC
    Secteur : Industrie

    Informations forums :
    Inscription : Juillet 2005
    Messages : 9 810
    Points : 20 970
    Points
    20 970
    Par défaut
    Avec un arbre vide, ça crashe aussi ?
    Pas besoin de down/upcaster dans tes delete si tes destructeurs sont virtuels.

  4. #4
    Membre averti
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    99
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 99
    Points : 303
    Points
    303
    Par défaut
    Ouah! ça fait super plaisir d'avoir un peu de support! Grand merci!

    J'utilise Code::Blocks, mais le déboggueur (gdb ou cdb) refuse d'entrer dans le programme hote, (je pense que le fait que celui-ci ne soit pas compilé avec les intructions de déboggage y est pour quelque chose, et c'est un logiciel propriétaire dont je n'ai pas le code ^^).

    (Héhé, je me suis gratté la tête un instant en me demandant comment faire un arbre vide... me faut un café)
    Alors, j'ai donc fait un constructeur vide qui me crée juste un Noeud Arbre (oui, Arbre est dérivée de Noeud), et même affaire, crash après le system("pause");

    C'est noté pour les cast sur les delete, ça n'a pas posé de pb au compilateur! C'est bon a prendre ^^

    Hum, j'ai un diagramme de classes à jour si vous voulez avoir quelque chose de plus visuel! Suffit de demander!

    Je suis sûr que ça ne doit pas être sorcier, mais là, je trouve pas!


    Mango

  5. #5
    Rédacteur

    Avatar de Matthieu Brucher
    Profil pro
    Développeur HPC
    Inscrit en
    Juillet 2005
    Messages
    9 810
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Développeur HPC
    Secteur : Industrie

    Informations forums :
    Inscription : Juillet 2005
    Messages : 9 810
    Points : 20 970
    Points
    20 970
    Par défaut
    Si tu as du code, tu peux débugger avec les instructions de débuggage, et comme c'est toi qui codes...
    Et si un arbre vide crashe le programme, vérifie bien ce que tu fais.

  6. #6
    Membre averti
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    99
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 99
    Points : 303
    Points
    303
    Par défaut
    okay, je vais tout remettre à plat, je vous tiens au courant!
    En tout cas, ça m'a fait un petit break!

    Merci
    Mango

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

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

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Points : 16 213
    Points
    16 213
    Par défaut
    Deux idées :

    1/ Confusion calloc/new :

    Si tu as alloué avec calloc, tu dois libérer avec free (à vérifier, je ne connais pas le C), si tu as alloué avec new, tu dois libérer avec delete. Mélanger les deux est une erreur.

    Pas ailleurs, calloc ne fais qu'allouer de la mémoire, mais n'appelle pas les constructeurs. Donc, en général, quand on doit utilisr ce genre de fonctions en C++, le cycle est le suivant :
    - Allocation mémoire avec calloc
    - Création de l'objet avec placement new
    - Appel explicite au destructeur (pas delete)
    - Libération mémoire

    2/ Le destructeur de toutes tes classes de base polymorphiques est-il bien virtuel ?
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  8. #8
    Membre averti
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    99
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 99
    Points : 303
    Points
    303
    Par défaut
    Alors, j'ai tout repris calmement!

    Evidemment c'est plus facile comme ça. J'ai un peu avancé, je n'ai plus de plantage sur l'arbre vide.

    J'avais pas mal potassé la question du new/delete-vs-malloc/free (ya plein de cours sur ça sur internet, dont Thinking in C++, sur ce site même), mais ça n'avais pas résolu mon problème.

    J'ai repris mon "C++ pour les nuls" (mine de rien) et c'est en lisant tout ce qu'il contient sur les destructeurs que l'idée à germée: j'avais sans doute des pointeurs mal initialisés! Du coup il nettoyait où fallait pas...

    Par sécurité j'ai donc transformé mon vecteur en pointeur sur vecteur alloué sur le tas. Du coup je peux le mettre a NULL s'il le faut etc... et delete ne fait rien de grave sur un pointeur NULL selon ce que j'ai lu.
    J'ai aussi vérifié mon destructeur de ma classe de base Noeud qui était bien virtuel.

    Je suis en train de descendre dans mon arbre en vérifiant tous mes pointeurs, enlevant les transtypages inutiles etc...

    Vous avez dû en voir passer des centaines des comme ça! Désolé!
    Je marque pas comme résolu, mais je suis sur la bonne voie! Je le marquerai comme résolu quand ça sera sûr

    Merci pour vos conseils!
    Dani

  9. #9
    Membre averti
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    99
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 99
    Points : 303
    Points
    303
    Par défaut
    Youhou!

    Merci a tous de m'avoir aiguillé, j'ai repris tout ça plus calmement hier après midi et ce matin et voilà, mes destructeurs s'appellent en cascade sans que ça plante!

    Le fond du problème:
    C'est peut être un problème de conception: dans la racine de mon arbre j'avais aussi la racine d'un document TinyXML (très pratique cette petite lib). Et dans chaque Noeud, j'avais aussi un TiXmlElement que j'essayais de détruire, mais il y avait des appels de destructeurs sur des objets dejà detruits... (TinyXml n'a pas l'air de détruire son arbre en mettant à NULL ses petits pointeurs, d'où les crashs, mais c'est aussi interessant de regarder comment ils font leur arbre! ça à l'air plus propre qu'avec des vecteurs... )

    J'ai donc sorti ma racine XML en dehors de l'arbre et enlevé les "delete TiXmlEl" du destructeur de Noeuds. Ca a résolu mes plantages.
    Je detruit mon arbre XML et mon arbre perso séparément.

    Néanmoins, j'ai une fuite de mémoire de 10Mo à chaque éxécution!! Mais c'est un autre problème! Donc --> Résolu!

    Merci encore
    Dani

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [Wamp] Problème d'insertion avec quote d'un formulaire
    Par cyberdevelopment dans le forum EDI, CMS, Outils, Scripts et API
    Réponses: 1
    Dernier message: 20/08/2006, 18h55
  2. [SQL-Server] Problèmes de guillemets et quotes dans un INSERT
    Par gregb34 dans le forum PHP & Base de données
    Réponses: 2
    Dernier message: 05/05/2006, 09h40

Partager

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