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

C++ Discussion :

violation d'accès en release avec tinyXml


Sujet :

C++

  1. #1
    Membre du Club
    Homme Profil pro
    Collégien
    Inscrit en
    Février 2016
    Messages
    20
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : Collégien
    Secteur : Alimentation

    Informations forums :
    Inscription : Février 2016
    Messages : 20
    Points : 46
    Points
    46
    Par défaut violation d'accès en release avec tinyXml
    Bonjour,
    je travaille sous c++ Builder et suis en train de faire un programme qui fait des recherches dans des fichiers xml. Pour cela j'utilise TinyXml.
    Je suis arrivé à terme de mon programme après test en débug.
    Une fois que j'essaie de le mettre en release mon programme fait une violation d'accès (vers un pointeur non nul) lors de la recherche.

    Cela se fait uniquement lorsque j'essaie de lire une valeur dans le fichier XML, (j'ai pu le vérifié à l'aide de MessageBox avant et après l'instruction).
    Apres recherche on m'a dit que cela venait d'une variable mal initialisée, mais ça ne vient pas de la (je ne pense pas être passé à coté de l'une d'elle).

    Avez-vous des pistes pour pouvoir m'expliquer ce qui ne va pas en release s'il vous plait ?
    Je vous joins le code provoquant mon erreur.


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    TiXmlDocument monFichier((path + fileName).c_str());
    	if(monFichier.LoadFile()){
    		TiXmlHandle monHandle(&monFichier);
    		monHandle = monHandle.FirstChildElement();
    
    		if (monHandle.ToElement() != NULL) {
    			maNode = monHandle.ToNode();
    			ParcourirNoeud(maNode);
    		} 
    
    
    void __fastcall ParserXml::ParcourirNoeud(TiXmlNode* NodeAParcourir, bool estDansLeParent){
    	bool dansLeNoeudParent = false;
    	while(NodeAParcourir){
    	//test
    		AnsiString nom, valeur;
    		ShowMessage("ok");
    		nom = NodeAParcourir->Value();
    		ShowMessage("et la ça bug");
    	//
    ....
    }
    Merci, bonne journée

  2. #2
    Expert éminent
    Avatar de Pyramidev
    Homme Profil pro
    Tech Lead
    Inscrit en
    Avril 2016
    Messages
    1 490
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Tech Lead

    Informations forums :
    Inscription : Avril 2016
    Messages : 1 490
    Points : 6 189
    Points
    6 189
    Par défaut
    Bonjour,

    Est-ce que ça plante tout de suite après le premier "ok" ou bien après plusieurs "ok" ?
    Dans le premier cas, je n'ai pas de piste.
    Dans le deuxième cas, il faudrait qu'on voit le reste de la boucle while qui modifie sûrement NodeAParcourir (autrement, la condition du while n'aurait pas de sens).

  3. #3
    Membre du Club
    Homme Profil pro
    Collégien
    Inscrit en
    Février 2016
    Messages
    20
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : Collégien
    Secteur : Alimentation

    Informations forums :
    Inscription : Février 2016
    Messages : 20
    Points : 46
    Points
    46
    Par défaut
    Merci pour ta réponse
    et oui malheureusement ça plante dès la 1ère itération ... Pourtant je fais des test sur le document, le handle et la node, à ne rien comprendre ...

    Pour te répondre ma boucle while a du sens. Je fais NextSibling(), si il n'y en a plus il devient NULL donc on sort de la boucle.
    Je mets l'essentiel de ma fonction (en enlevant les divers test que je fais sur la node qui ne la modifie pas pour autant).

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    void __fastcall ParserXml::ParcourirNoeud(TiXmlNode* NodeAParcourir, bool estDansLeParent){
    	bool dansLeNoeudParent = false;
    	while(NodeAParcourir){
    	//test
    		AnsiString nom, valeur;
    		ShowMessage("ok");
    		nom = NodeAParcourir->Value();
    		ShowMessage("ok");
    		if(NodeAParcourir->ToElement()->FirstAttribute())
    		valeur = NodeAParcourir->ToElement()->FirstAttribute()->Value();
    	//
    		if(!NodeAParcourir->NoChildren()){
    			ParcourirNoeud(NodeAParcourir->FirstChild(), estDansLeParent);
    		}
     
    		NodeAParcourir = NodeAParcourir->NextSibling();
    	}
    }

  4. #4
    Expert éminent
    Avatar de Pyramidev
    Homme Profil pro
    Tech Lead
    Inscrit en
    Avril 2016
    Messages
    1 490
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Tech Lead

    Informations forums :
    Inscription : Avril 2016
    Messages : 1 490
    Points : 6 189
    Points
    6 189
    Par défaut
    Je ne sais pas ce qui a fait crasher le programme.
    Cependant, je vois que tu oublies de tester que ToElement() retourne un pointeur non nul.

    Voici une autre version du code de ta fonction ParcourirNoeud :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    void __fastcall ParserXml::ParcourirNoeud(const TiXmlNode& PremierNoeud, bool estDansLeParent)
    {
    	bool dansLeNoeudParent = false;
    	for(const TiXmlNode* NodeAParcourir = &PremierNoeud;
    	    NodeAParcourir != NULL;
    	    NodeAParcourir = NodeAParcourir->NextSibling())
    	{
    	//test
    		ShowMessage("ok");
    		AnsiString nom = NodeAParcourir->Value();
    		ShowMessage("ok");
    		AnsiString valeur;
    		const TiXmlElement* element = NodeAParcourir->ToElement();
    		if(element) {
    			const TiXmlAttribute* attribut = element->FirstAttribute();
    			if(attribut)
    				valeur = attribut->Value();
    		}
    	//
     
    		const TiXmlNode* premierEnfant = NodeAParcourir->FirstChild();
    		if(premierEnfant != NULL)
    			ParcourirNoeud(*premierEnfant, estDansLeParent);
    	}
    }

  5. #5
    Membre du Club
    Homme Profil pro
    Collégien
    Inscrit en
    Février 2016
    Messages
    20
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : Collégien
    Secteur : Alimentation

    Informations forums :
    Inscription : Février 2016
    Messages : 20
    Points : 46
    Points
    46
    Par défaut
    J'ai testé ta solution mais cela a empiré mon cas. Maintenant ça plante même en débug lorsque l'on passe par :
    Citation Envoyé par Pyramidev Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    		const TiXmlElement* element = NodeAParcourir->ToElement();
    		if(element) {
    			const TiXmlAttribute* attribut = element->FirstAttribute();
    			if(attribut)
    				valeur = attribut->Value();
    "valeur" contient des valeurs étonnantes, à la 1ère itération une flèche, à la seconde un carré puis à la 3eme plante...

  6. #6
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 128
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 128
    Points : 33 055
    Points
    33 055
    Billets dans le blog
    4
    Par défaut
    Tu check que toElement fonctionne, puis le transformes en node avec toNode, puis retourne en element. C'est au mieux bancal

  7. #7
    Membre du Club
    Homme Profil pro
    Collégien
    Inscrit en
    Février 2016
    Messages
    20
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : Collégien
    Secteur : Alimentation

    Informations forums :
    Inscription : Février 2016
    Messages : 20
    Points : 46
    Points
    46
    Par défaut
    Merci pour ta remarque, c'est vrai que c'était bancal et je viens de corriger, même si dans ParcourirNoeud la première chose que je fais est de vérifier que ma node n'est pas NULL.
    Si vous avez d'autres suggestions n'hésitez pas

  8. #8
    Expert éminent sénior
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2005
    Messages
    5 174
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2005
    Messages : 5 174
    Points : 12 301
    Points
    12 301
    Par défaut
    mais cela a empiré mon cas. Maintenant ça plante même en début
    Je signale juste que ceci est une très bonne nouvelle, on base d'un bug "aléatoire" à un bug que le runtime de Debug aide à corriger.

  9. #9
    Expert éminent
    Avatar de Pyramidev
    Homme Profil pro
    Tech Lead
    Inscrit en
    Avril 2016
    Messages
    1 490
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Tech Lead

    Informations forums :
    Inscription : Avril 2016
    Messages : 1 490
    Points : 6 189
    Points
    6 189
    Par défaut
    Une solution serait de raccourcir et simplifier le code.
    Plus le code est petit est simple, plus il est facile à maintenir.

    Après une lecture rapide de la documentation de TinyXml, le plus simple pour parcourir un fichier XML en entier est de créer une classe qui dérive de TiXmlVisitor puis d'appeler la fonction TiXmlDocument::Accept (TiXmlVisitor *content) const.

    Voici le code source de TiXmlVisitor :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    class TiXmlVisitor
    {
    public:
        virtual ~TiXmlVisitor() {}
     
        virtual bool VisitEnter( const TiXmlDocument& /*doc*/ )         { return true; }
        virtual bool VisitExit( const TiXmlDocument& /*doc*/ )          { return true; }
     
        virtual bool VisitEnter( const TiXmlElement& /*element*/, const TiXmlAttribute* /*firstAttribute*/ )    { return true; }
        virtual bool VisitExit( const TiXmlElement& /*element*/ )       { return true; }
     
        virtual bool Visit( const TiXmlDeclaration& /*declaration*/ )   { return true; }
        virtual bool Visit( const TiXmlText& /*text*/ )                 { return true; }
        virtual bool Visit( const TiXmlComment& /*comment*/ )           { return true; }
        virtual bool Visit( const TiXmlUnknown& /*unknown*/ )           { return true; }
    };
    Voici ce que dit la documentation de TiXmlVisitor :
    If you call the Accept() method, it requires being passed a TiXmlVisitor class to handle callbacks. For nodes that contain other nodes (Document, Element) you will get called with a VisitEnter/VisitExit pair. Nodes that are always leaves are simply called with Visit().

    If you return 'true' from a Visit method, recursive parsing will continue. If you return false, no children of this node or its sibilings will be Visited.

    All flavors of Visit methods have a default implementation that returns 'true' (continue visiting). You need to only override methods that are interesting to you.

    Generally Accept() is called on the TiXmlDocument, although all nodes suppert Visiting.
    Par exemple, soit MonVisiteurDeTiXml une classe qui dérive publiquement de TiXmlVisitor.
    Tu peux faire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    // La fonction suivante sera appelée pour tous les éléments du fichier XML :
    bool MonVisiteurDeTiXml::VisitEnter( const TiXmlElement& element, const TiXmlAttribute* firstAttribute )
    {
        const AnsiString nomElement            = element.Value();
        const AnsiString nomPremierAttribut    = firstAttribute ? firstAttribute->Name()  : "";
        const AnsiString valeurPremierAttribut = firstAttribute ? firstAttribute->Value() : "";
        ...
        return true;
    };
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    TiXmlDocument monFichier((path + fileName).c_str());
    if(monFichier.LoadFile()){
        MonVisiteurDeTiXml monVisiteur;
        monFichier.Accept(&monVisiteur);
        ...
    }
    ...

  10. #10
    Membre émérite
    Avatar de skeud
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2011
    Messages
    1 091
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France, Loire Atlantique (Pays de la Loire)

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

    Informations forums :
    Inscription : Juin 2011
    Messages : 1 091
    Points : 2 724
    Points
    2 724
    Billets dans le blog
    1
    Par défaut
    Si mes souvenir de tixml sont bon, la fonction membre "value()" retourne la valeur du noeud courant, hors pour récupéré la valeur d'un noeud, il faut prendre la valeur du noeud fils qui doit etre un noeud texte.

    Donc pour:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    <balise>valeur</balise>
    Il faut faire:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    noeud->FirstChild()->Value()

  11. #11
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 128
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 128
    Points : 33 055
    Points
    33 055
    Billets dans le blog
    4
    Par défaut
    value dépend du type de l'objet.
    Sur un node ça retourne le nom de la balise. Pour récupérer le texte à l'intérieur il faut prendre le child effectivement. Il faudra aussi peut-être le cast en text

  12. #12
    Membre du Club
    Homme Profil pro
    Collégien
    Inscrit en
    Février 2016
    Messages
    20
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : Collégien
    Secteur : Alimentation

    Informations forums :
    Inscription : Février 2016
    Messages : 20
    Points : 46
    Points
    46
    Par défaut
    Après multitudes essais le code s'est mis à fonctionner !

    J'ai fais différents essais :
    -avancer pas à pas pour se rendre compte que TiXmlElement>FirstAttribute()->Value() retournait n'importe quoi (quand il possédait un attribut bien évidemment) et toutefois constater que TiXmElement->Value() et TiXmlNode->Attribute("nom d'un attribut spécifique") marchaient parfaitement
    -créer un projet pour isoler le problème, se rendre compte qu'à la 1ere compilation et éxecution cela fonctionnait
    -en conclure que c'était au cours de l'exécution que quelque chose faisait tout merder
    -revenir sur mon code principal et mettre le code sensible comme touuute 1ère instruction
    -voir que ça n'a rien changé
    -pleuré, me mettre en pls

    ET LA LA DERNIERE CHANCE AVANT DE PARTIR EN WEEK END
    -changer les fichiers d'inclusion de
    à
    -admirer le résultat ...
    -remettre comme avant pour voir si la destination de tinyxml était différente
    -voir qu'il fonctionne aussi maintenant dans son état antérieur
    -ne pas voir de changement sur les fichiers d'inclusions mais qui y prête attention ?

    C++ Builder mon ami pour la vie

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

Discussions similaires

  1. [TinyXML] Violation d'accès TXmlDocument
    Par moumout666 dans le forum XML
    Réponses: 0
    Dernier message: 21/10/2008, 11h05
  2. Violation d'accès avec activeX dans IE
    Par Eric Beaumard dans le forum Web & réseau
    Réponses: 1
    Dernier message: 12/09/2008, 20h08
  3. violation d'accès avec fenetre mdi
    Par rjuju dans le forum Delphi
    Réponses: 4
    Dernier message: 15/11/2006, 14h31
  4. Réponses: 1
    Dernier message: 02/08/2006, 17h37
  5. Violation d'accès avec les composants Word 97/ 2000
    Par edechaux dans le forum Composants VCL
    Réponses: 3
    Dernier message: 07/03/2006, 09h48

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