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

SL & STL C++ Discussion :

pb de vector (encore un)


Sujet :

SL & STL C++

  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    167
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2006
    Messages : 167
    Par défaut pb de vector (encore un)
    Bonjour,

    Ca fait un certain temps que j'utilise les vector mais là, je suis face à une incompréhension total.

    J'utilise une classe GLignage qui est défini suivant les règles simples des 4 (constructeur,destructeur,recopie, op=). Ca fait 1 semaine que je créé, détruit, copie des objets de cet classe et tout semble rouler pour le mieux.
    Récemment, je décide de rajouter une petite méthode...voici le code (enfin le seul point qui "bug" ...) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    bool GLignage::soudure(vector<GLignage>& amas)
      {
       if(amas.size()==0)
         {
    	  GLignage glig=*this;
    	  GLignage glig2=glig;
    	  amas.clear();
    	  amas.push_back(glig);
    	  amas.push_back(GLignage(glig.transseg,glig.lignage));
    	  return 1;
         }
     }
    Bon alors c'est un code con, je veux juste faire le push_back(*this) mais j'ai testé plein de détail pour être sûr que ça vient du vector. Après plusieurs heures d'analyse des variables avec mon debuggeur (sous eclipse avec les options classique C++...), j'en suis à ça : le vector passé en référence a tout ses conteneurs (_M_start, _M_finish, _M_end_of_storage) sur 0x00000000 (donc le NULL)... ce qui cause un soucis visiblement...

    qq1 a-t-il déjà rencontré ça? Comment passé à travers?

    Merci d'avance.

  2. #2
    Membre émérite Avatar de MatRem
    Profil pro
    Inscrit en
    Décembre 2002
    Messages
    750
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2002
    Messages : 750
    Par défaut
    Il faudrait que tu montres comment tu appelles GLignage::soudure.

    Sinon pour le type bool il existe true et false .

  3. #3
    Membre expérimenté
    Profil pro
    Dev
    Inscrit en
    Décembre 2007
    Messages
    191
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations professionnelles :
    Activité : Dev

    Informations forums :
    Inscription : Décembre 2007
    Messages : 191
    Par défaut
    et ta fonction ne retourne rien si le test echoue!

    PS à quoi sert : GLignage glig2=glig; ?

  4. #4
    Membre confirmé
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    167
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2006
    Messages : 167
    Par défaut
    OK

    Alors, pour le PS... à rien, c'était pour vérifier la recopie dans le debuggeur et s'assurer que *this passait bien
    Je le rappele, je veux juste faire un amas.push_back(*this);

    Pour l'autre demande... elle est également légitime :

    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
    26
    27
    28
    29
     
    //je peux extraire du code cette partie où se situe le pb...
     
    vector<GLignage> recup_tmp;
    vector<GLignage> recup_temp;
     
    //[...] du code sans liaison avec les objets du pb
     
    //une fonction qui remplit recup_temp... au moins 1000 lignes de code en tout
    //alors... mais validé et testé avec succès (50 tests, c'est à dire 2 fois
    //chaque configurations possibles). Avec le debuggeur, on peut observer que
    //l'adresse est inchangée (bonne nouvelle :D) et que les conteneurs sont bien
    //remplis dans un cas de remplissage et inchangé sinon...
     
    if(recup_temp.size()==0)
    	    {
    //code... blablabla
    	    }
    else 
      {
       //ressouder
       for(vector<GLignage>::iterator ite=recup_temp.begin(); ite<recup_temp.end();++ite)
         {
           if(!((*ite).soudure(recup_tmp)))
    	 {// le pb est là!
    	   recup_tmp.push_back(*recup_temp.begin());
    	 }
         }
    }
    Donc je recopie simplement recup_temp dans recup_tmp... avec une gestion de cas lié à ma classe GLignage...simple pourtant!
    ... mais pourquoi des conteneurs sur NULL?! Ca par contre, c'est la première fois! Normalement, faire un vector<truc> vect; ... ça devrait pas.

  5. #5
    Membre averti
    Profil pro
    Inscrit en
    Février 2007
    Messages
    26
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 26
    Par défaut
    Donc je recopie simplement recup_temp dans recup_tmp... avec une gestion de cas lié à ma classe GLignage...simple pourtant!
    ... mais pourquoi des conteneurs sur NULL?! Ca par contre, c'est la première fois! Normalement, faire un vector<truc> vect; ... ça devrait pas.
    bonjour, si le debuggeur te signal comme lieu de crash un lieu comme : vecteur<truc>vect; ce qui est normalement sain, ça veut dire que le probléme est ailleurs. ça peut etre un memory corruption provoqué par un autre pointeur, et dont les symptomes n'apparaissent qu'un peu plus loin, dans une ligne portant saine.

    je te propose de revoir le parcours de ton programme et de ne pas te focaliser seulement sur le point qui cause le crash visiblement.

  6. #6
    Membre confirmé
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    167
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2006
    Messages : 167
    Par défaut
    Ouais... j'ai essayé de changer de place... et en fait j'ai pareil.
    C'est donc lié à qq chose d'intrinsèque à mon code.

    Eclipse me dit : Attempt to take contents of a non-pointer value.
    ... j'ai toujours un vecteur initialisé sur des conteneurs vides.

    je passe dans ces fonctions un "vector<GLignage>& vect". Dans une autre fonction ou je fais pareil, ça pose pas de problème. Dans les 2 cas, je fais simplement la définition du vect avant de le transmettre. Si c'était ça, ça devrait le faire dans les 2 cas.

    J'suis vraiment bloqué

  7. #7
    Membre éclairé Avatar de befalimpertinent
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    561
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Gironde (Aquitaine)

    Informations forums :
    Inscription : Avril 2007
    Messages : 561
    Par défaut
    Fais vois le code du constructeur de recopie et de l'opérateur d'affectation de GLignage.
    C'est souvent ici que ce situe ce genre de problème.

  8. #8
    Membre confirmé
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    167
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2006
    Messages : 167
    Par défaut
    oui :

    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
     
    //_____Constructeur de recopie_____//   
     GLignage(const GLignage& glig)
       {
        if(&glig!=this)
          {
           transseg=glig.transseg;
           //lignage.clear();
           lignage=glig.lignage;
          }    
       }
     
    //_____Operateur d'affectation_____//   
     GLignage& operator=(GLignage& glig) 
       {
        if(&glig!=this)
          {
           transseg=glig.transseg;
           lignage=glig.lignage;
          }
        return *this;
       }

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

    Informations forums :
    Inscription : Février 2007
    Messages : 26
    Par défaut
    Citation Envoyé par DEVfan Voir le message
    Ouais... j'ai essayé de changer de place... et en fait j'ai pareil.
    C'est donc lié à qq chose d'intrinsèque à mon code.

    Eclipse me dit : Attempt to take contents of a non-pointer value.
    ... j'ai toujours un vecteur initialisé sur des conteneurs vides.

    je passe dans ces fonctions un "vector<GLignage>& vect". Dans une autre fonction ou je fais pareil, ça pose pas de problème. Dans les 2 cas, je fais simplement la définition du vect avant de le transmettre. Si c'était ça, ça devrait le faire dans les 2 cas.
    J'suis vraiment bloqué
    oui justement! c'est pas à cause du vecteur que tu passe en paramètre, puisque tu le crée juste avant. j'avais aussi exactement le meme problème, et je l'ai réglé en parcourant mon programme depuis le début et en arrangeant tout ce qui me parait louche (meme si il a l'air de marcher) et quand j'ai terminé les arrangements, le problème a disparu. le code du vecteur etait juste le bouc émissaire en effet

  10. #10
    Membre confirmé
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    167
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2006
    Messages : 167
    Par défaut
    Soit!

    Mais alors qu'entends-tu par arrangements? ...Parce que mes opérateurs (recopie, =, etc.) me semblent bon et stl est sensé être sûr... Je vais faire un test à part sans aucun pointeur pour pister une éventuelle fuite ... mais avoir une erreur après 5000 lignes de codes... ça va être long pour trouver ça!!

  11. #11
    Membre éclairé Avatar de befalimpertinent
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    561
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Gironde (Aquitaine)

    Informations forums :
    Inscription : Avril 2007
    Messages : 561
    Par défaut
    Si je te demandais le code de la recopie et de l'affectation c'est que le type d'erreur que tu as peut s'expliquer par une mauvaise gestion des pointeurs à cet endroit.

    Je m'explique :
    Si ton objet possède un pointeur vers un autre objet et que lors d'une copie tu te contentes d'affecter membres à membres, tu va faire pointer deux objets vers la même case mémoire.
    Si plus loin un de tes deux objets est détruit et que dans ton destructeur il y a un delete sur le pointeur, cela va faire pointer le membre de ton deuxième objet ... dans le vide.
    Enfin bref je commencerai par vérifier recopie, affectation et destructeur à ce niveau.
    Si rien ne parait suspect il faudra peut être te tourner vers des outils qui analysent les problèmes mémoires d'un programme (purify, valgrind, ...). Mais personnellement je n'en n'ai jamais utiliser.

    Bon courage

  12. #12
    Membre confirmé
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    167
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2006
    Messages : 167
    Par défaut
    OK.

    Dans mon code, à ce niveau, je n'utilise pas de pointeur, si ce n'est ...this. Je m'appuie fortement sur la stl. D'ailleurs à ce sujet, peut-on me confirmer que les contenaires font bien appelent aux delete des classes contenus... donc vide bien proprement! Et aussi, doit-on faire clear() ou bien les conteneurs sont-ils proprement vidé?

    Encore une idée, est-ce que le pb pourrait venir des const ... la recopie dans mon cas fait appel à du const mais ce peut-il qu'un objet soit transmis en non const et donc face du par défaut?

    Merci.

  13. #13
    Membre expérimenté
    Profil pro
    Dev
    Inscrit en
    Décembre 2007
    Messages
    191
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations professionnelles :
    Activité : Dev

    Informations forums :
    Inscription : Décembre 2007
    Messages : 191
    Par défaut
    Citation Envoyé par DEVfan Voir le message
    OK.

    Dans mon code, à ce niveau, je n'utilise pas de pointeur, si ce n'est ...this. Je m'appuie fortement sur la stl. D'ailleurs à ce sujet, peut-on me confirmer que les contenaires font bien appelent aux delete des classes contenus... donc vide bien proprement! Et aussi, doit-on faire clear() ou bien les conteneurs sont-ils proprement vidé?
    les conteneurs ne font en aucun cas appel à des delete. On peut créer des conteneurs de variables non-pointeurs, donc faire un "delete automatique" n'aurait pas de sens. Tu dois faire delete pour chaque pointeur vers ta classe que tu as inséré dans ton conteneur toi-même. De plus si tu fais delete sur tes pointeurs, les variables pointeurs ne disparaissent pas (elles pointent juste vers une zone désallouée) donc tu dois les supprimer toi même de ton conteneur. (chaque conteneur à une méthode adéquate, clear() par exemple pour tout supprimer)



    Encore une idée, est-ce que le pb pourrait venir des const ... la recopie dans mon cas fait appel à du const mais ce peut-il qu'un objet soit transmis en non const et donc face du par défaut?

    Merci.
    Le const est surtout là pour éviter au programmeur de faire des erreurs, justement en modifiant par hasard un truc qu'il n'aurait pas du.Cela indique au compilateur d'interdire toute modification de la variable, ou appel de fonction qui n'utilise pas cet argument en const. C'est donc plutot une bonne chose de le mettre ,ça évitera une partie des erreurs possibles.

    Maintenant, si lors du constructeur de recopie le compilateur accepte le transfert d'un simple pointeur (donc modifiable), il devrait au moins afficher un warning il me semble.

  14. #14
    Membre confirmé
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    167
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2006
    Messages : 167
    Par défaut
    Ah... ça peut expliquer des choses!! Mais c'est contraire à la logique, faire appel à delete sur chaque objet du conteneur puis faire clear()! J'avais cru lire le contraire ailleurs!
    Et vu le nb d'objet de cette classe que j'ai créé avant... ça m'étonne.

    Pour le warning, ok et de ce côté, aucun.

    EDIT : en fait, même si mon destructeur élimine terme à terme bêtement, ça devrait marcher... cette classe ne comporte que des éléments simples
    ...comment un pb de mémoire pourrait donc émerger!?

    EDIT2 : ...j'ai prolongé le raisonnement... si le conteneur ne peut pas faire de destructeur, il ne devrait pas pouvoir faire de constructeur par défaut aussi.... et bien c'est presque vrai dans mon cas... j'ai juste 1 cas où c'est pas vrai. A part ce cas donc, je créé des iterateur null sauf si j'initialise le conteneur

    ...Je viens de me rendre compte que j'utilisais un peu rapidement conteneur jusque là... ils s'agissaient en fait des iterateurs du conteneur : Le conteneur a une adresse mais les iterateurs (comme spécifié en nom dans le premier post ...first, finish et end ... sont à NULL)

    EDIT3 : ...ça devient grave docteur, le compilateur ne veut plus que je fasse un iterator1<iterator2 ... c'est quoi ces quacks chelu? On m'a verolé Eclipse?!

  15. #15
    Membre expérimenté
    Profil pro
    Inscrit en
    Octobre 2005
    Messages
    267
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2005
    Messages : 267
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
       //ressouder
       for(vector<GLignage>::iterator ite=recup_temp.begin(); ite<recup_temp.end();++ite)
         {
           if(!((*ite).soudure(recup_tmp)))
    	 {// le pb est là!
    	   recup_tmp.push_back(*recup_temp.begin());
    	 }
         }
    Donc je recopie simplement recup_temp dans recup_tmp...
    [EDIT]: Oups, elle est où la suite...... Voir le prochain message....

  16. #16
    Membre expérimenté
    Profil pro
    Inscrit en
    Octobre 2005
    Messages
    267
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2005
    Messages : 267
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
       //ressouder
       for(vector<GLignage>::iterator ite=recup_temp.begin(); ite<recup_temp.end();++ite)
         {
           if(!((*ite).soudure(recup_tmp)))
    	 {// le pb est là!
    	   recup_tmp.push_back(*recup_temp.begin());
    	 }
         }
    Donc je recopie simplement recup_temp dans recup_tmp...
    Non, tu ajoutes le premier élément de recup_temp à recup_tmp. Et, si dans ta fonction soudure, tu modifie ton vecteur, les itérateurs deviennent invalides.

  17. #17
    Membre confirmé
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    167
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2006
    Messages : 167
    Par défaut
    Dans soudure, je modifie effectivement le vecteur (sinon pourquoi le passer)... et en quoi ça invalide les iterateurs??? A quoi sert donc une classe si on ne peut pas y toucher!! (rq : passé en référence)

    Pour le détail ... oui en effet je recopie que le premier... mais une partie est masqué dans soudure justement.

  18. #18
    Membre expérimenté
    Profil pro
    Inscrit en
    Octobre 2005
    Messages
    267
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2005
    Messages : 267
    Par défaut
    Quand la structure du vecteur est modifié, les itérateurs sont invalides.
    Si tu supprime un élément, si tu en ajoutes, il peut y avoir une réalocation en mémoire. Donc les itérateurs que tu as utilisé précédemment pointent... là où il ne devraient pas.
    Tu n'y peux rien, c'est comme ça...

  19. #19
    Membre confirmé
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    167
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2006
    Messages : 167
    Par défaut
    oui effectivement. Mais ce qui me surprends le plus, c'est les pointeurs vers NULL. Parce que du coup faire un push_back... il sait plkus le faire!! :

    Vecteur d'adresse ..bidule (non NULL)
    et iterateur tous à NULL
    => pb!!!

  20. #20
    yan
    yan est déconnecté
    Rédacteur
    Avatar de yan
    Homme Profil pro
    Ingénieur expert
    Inscrit en
    Mars 2004
    Messages
    10 035
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur expert
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2004
    Messages : 10 035
    Par défaut
    Citation Envoyé par DEVfan Voir le message
    Dans soudure, je modifie effectivement le vecteur (sinon pourquoi le passer)... et en quoi ça invalide les iterateurs??? A quoi sert donc une classe si on ne peut pas y toucher!! (rq : passé en référence)

    Pour le détail ... oui en effet je recopie que le premier... mais une partie est masqué dans soudure justement.
    Bonjour que fait tu dans soudure sur le vector??

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. Programmer encore en VB 6 c'est pas bien ? Pourquoi ?
    Par Nektanebos dans le forum Débats sur le développement - Le Best Of
    Réponses: 85
    Dernier message: 10/03/2009, 14h43
  2. Réponses: 19
    Dernier message: 14/11/2006, 16h45
  3. TEdit (encore)
    Par dj.motte dans le forum C++Builder
    Réponses: 5
    Dernier message: 23/12/2002, 19h02
  4. TPalette (encore)
    Par Flipper dans le forum Langage
    Réponses: 3
    Dernier message: 28/11/2002, 23h45

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