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

Langage C++ Discussion :

STL parcourir une map.


Sujet :

Langage C++

  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Novembre 2011
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2011
    Messages : 7
    Par défaut STL parcourir une map.
    Bonjour,

    dans un programme contenant une map, j'ai besoin de parcourir la map en question, afin de récupérer un élément. J'écris donc le code suivant:

    Mais lors de l’exécution j'ai une erreur de segmentation. Je ne vois pas du tout comment faire.
    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
     
    Forme* Usine::trouverForme(const string& chaine)
    {
            map<string, Forme*>::iterator it;
    	it= mymap.find(chaine);
    	if( it==mymap.end() )
    	{
    		cout << "non trouvé" << endl;
    		return(NULL);
     
    	}
    	else
    	{
    		cout << "trouvé" << endl;
    		return((*it).second);
    	}
    }

  2. #2
    Membre émérite Avatar de Steph_ng8
    Homme Profil pro
    Doctorant en Informatique
    Inscrit en
    Septembre 2010
    Messages
    677
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Doctorant en Informatique

    Informations forums :
    Inscription : Septembre 2010
    Messages : 677
    Par défaut
    Bonsoir.

    Tu es sûr que c'est dans cette fonction que survient l'erreur de segmentation ?
    Qu'est-ce que mymap (une variable membre, une variable membre statique, une variable globale, etc.) ?
    Usine::trouverForme est une fonction membre statique ou non ?
    Usine::trouverForme peut-elle être appelée lors de la construction d'un objet statique ?

    Je n'ai pas une grosse visibilité de ton projet, mais ça me fait penser à un problème (vicieux...) que j'ai rencontré récemment...
    F.A.Q. C++: Qu'est-ce que le 'fiasco dans l'ordre d'initialisation des variables statiques' ?

    Si ce n'est pas ça, il va falloir mettre un peu plus de code pour que l'on puisse y voir quelque chose...

  3. #3
    Membre à l'essai
    Profil pro
    Inscrit en
    Novembre 2011
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2011
    Messages : 7
    Par défaut
    mymap est ma donnée privé, de la forme map<string, Forme*>.

    dans mon header voici le prototype de créer forme. (pas de statique)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Forme* creerForme(const string& chaine)
    creerForme n'est pas appelé lors de la construction d'un objet statique. Il s'agit d'une foction qui ressort un objet de ma map correspondant à la clé qu'il a en argument.

    L'erreur de segmentation survient lors du test du programme quand on appelle creerForme.

  4. #4
    Membre émérite Avatar de Steph_ng8
    Homme Profil pro
    Doctorant en Informatique
    Inscrit en
    Septembre 2010
    Messages
    677
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Doctorant en Informatique

    Informations forums :
    Inscription : Septembre 2010
    Messages : 677
    Par défaut
    Dans ce cas, si tu pouvais au moins mettre le code de Usine::creerForme...

  5. #5
    Membre à l'essai
    Profil pro
    Inscrit en
    Novembre 2011
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2011
    Messages : 7
    Par défaut
    problème de recopiage de code, trouverFrome=creerForme (j'ai changé le nom pour que la fonction soit plus compréhensible.

    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
     
    Forme* Usine::creerForme(const string& chaine)
    {
    	map<string, Forme*>::iterator it;
    	it= mymap.find(chaine);
    	if( it==mymap.end() )
    	{
    		cout << "non trouvé" << endl;
    		return(NULL);
     
    	}
    	else
    	{
    		cout << "trouvé" << endl;
    		return((*it).second);
    	}
    }

  6. #6
    Membre émérite Avatar de Steph_ng8
    Homme Profil pro
    Doctorant en Informatique
    Inscrit en
    Septembre 2010
    Messages
    677
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Doctorant en Informatique

    Informations forums :
    Inscription : Septembre 2010
    Messages : 677
    Par défaut
    Ok.

    Citation Envoyé par peapol Voir le message
    L'erreur de segmentation survient lors du test du programme quand on appelle creerForme.
    De quel test parles-tu ?
    Si c'est celui de la ligne 6, ça veut certainement dire que mymap n'est pas (complètement) construit au moment de l'appel de la fonction.

    Je ne vois pas d'autre explication.
    Mais encore une fois, avec si peu de code, c'est difficile de se rendre bien compte...

  7. #7
    Membre très actif
    Profil pro
    professeur des universités à la retraite
    Inscrit en
    Août 2008
    Messages
    364
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : professeur des universités à la retraite

    Informations forums :
    Inscription : Août 2008
    Messages : 364
    Par défaut
    Il serait sans doute de meilleure qualité de programmation de passer ta mymap en référence comme argument à ta fonction. On y verrait déjà plus clair.

  8. #8
    Membre à l'essai
    Profil pro
    Inscrit en
    Novembre 2011
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2011
    Messages : 7
    Par défaut
    Dans mon main j'ai:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    bool b;
    Forme* ptrF;
    string cle;
     
    cout << "quel forme voulez vous copier? " << endl;
    cin >> cle;
    ptrF=mon_usine.creerForme(cle);
    cout << "quel clés pour le nouveaux? " << endl;
    cin >> cle;
    b=mon_usine.ajouterForme(cle,ptrF);
    ma fonction creerForme (je l'ai modifié pour qu'elle soit plus courte)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    Forme* Usine::creerForme(const string& chaine)
    {
    	if( mymap.count(chaine)>0)
    	{
    		return(mymap[chaine]->dupliquer());
    	}
    	else
    	{
    		cout << "non trouvé" << endl;
    		return(NULL);
    	}
    ma fonction dupliquer dépend de ma classe forme, je l'ai testé elle fonctionne bien sans faute de segmentation (elle rend une copie d'une forme sous forme de pointeur)
    en données privé j'ai:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    private:
    	 map<string, Forme*> mymap;

  9. #9
    Membre émérite Avatar de Steph_ng8
    Homme Profil pro
    Doctorant en Informatique
    Inscrit en
    Septembre 2010
    Messages
    677
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Doctorant en Informatique

    Informations forums :
    Inscription : Septembre 2010
    Messages : 677
    Par défaut
    Si c'est bien ce que je pense, le problème vient finalement de Usine::ajouterForme...
    Ce serait possible d'en avoir le code ?

  10. #10
    Membre à l'essai
    Profil pro
    Inscrit en
    Novembre 2011
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2011
    Messages : 7
    Par défaut
    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
    bool Usine::ajouterForme(const string& chaine, Forme* ptrF)
    {
    	Forme* ptrF2;
    	ptrF2=ptrF->dupliquer();
    	map<string, Forme*>::iterator it;
    	it= mymap.find(chaine);
    	if( it==mymap.end() )
    	{
    		mymap.insert(pair<string, Forme*>(chaine,ptrF2));
    		return(1);
    	}
    	else
    	{
    		return(0);
    	}
     
    }

  11. #11
    Membre à l'essai
    Profil pro
    Inscrit en
    Novembre 2011
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2011
    Messages : 7
    Par défaut
    j'ai essayé avec un code plus court histoire de voir si ça venez de la méthode utilisé mais c'est pareil:
    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
     
    bool Usine::ajouterForme(const string& chaine, Forme* ptrF)
    {
    	Forme* ptrF2;
    	ptrF2=ptrF->dupliquer();
            if(mymap.count(chaine)>0)
    	{
    		return(0);
    	}
    	else
    	{
    		mymap.insert(pair<string, Forme*>(chaine,ptrF2));
    		return(1);
    	}
     
    }

  12. #12
    Membre émérite Avatar de Steph_ng8
    Homme Profil pro
    Doctorant en Informatique
    Inscrit en
    Septembre 2010
    Messages
    677
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Doctorant en Informatique

    Informations forums :
    Inscription : Septembre 2010
    Messages : 677
    Par défaut
    C'est exactement ce que je pensais...

    Si la clé n'est pas trouvée dans la map, Usine::creerForme retourne NULL.
    Valeur que tu passes directement à Usine::ajouterForme.
    Et ici : ptrF2=ptrF->dupliquer();, on tente de déréférencer NULL, et PAF !
    Segmentation fault...

    L'autre possibilité, c'est que dans Usine::ajouterForme, l'appel à Forme::dupliquer retourne NULL, que tu stockes dans mymap.
    Un appel ultérieur à Usine::creerForme tente de déréférencer ce NULL (return(mymap[chaine]->dupliquer());), et re-PAF !...

    Mais je dois dire que j'ai un peu de mal à voir la différence entre Usine::creerForme et Usine::ajouterForme.
    Je pense que tu devrais les fusionner en une seule.

    Ce qui est étrange, c'est que si une clé est déjà présente dans la map, tu dupliques l'objet associé dans Usine::creerForme, puis ensuite tu dupliques la copie dans Usine::ajouterForme.
    Quel est l'intérêt ?
    Penses-tu bien à libérer (delete) la copie intermédiaire ?

    Autre chose, lorsque tu veux ajouter une forme mais que la clé est déjà présente, tu ne libères pas la mémoire allouée pour créer la copie.

  13. #13
    Membre à l'essai
    Profil pro
    Inscrit en
    Novembre 2011
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2011
    Messages : 7
    Par défaut
    après avoir appliquer tes conseils ça fonctionne. Un grand merci à toi, maintenant que j'ai compris d'ou ça vient je vais chercher par moi même l'origine des autres segmentation fault dans la suite de mon programme

    sinon ajouter forme me permet de sortir une forme déja présente. Ce que ne fait pas ajouter forme

  14. #14
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Salut,

    Juste au passage, comme cela...

    A moins que tu ne travailles avec Qt qui arrive à gérer de manière plus ou moins intelligente le moment où il faut libérer la mémoire allouée à un pointeur, le code
    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
    bool Usine::ajouterForme(const string& chaine, Forme* ptrF)
    {
    	Forme* ptrF2;
    	ptrF2=ptrF->dupliquer();
    	map<string, Forme*>::iterator it;
    	it= mymap.find(chaine);
    	if( it==mymap.end() )
    	{
    		mymap.insert(pair<string, Forme*>(chaine,ptrF2));
    		return(1);
    	}
    	else
    	{
    		return(0);
    	}
    }
    risque de poser un énorme problème de fuite mémoire, du moins, si, comme je m'y attend, dupliquer alloue dynamiquement de la mémoire pour le pointeur renvoyé

    En effet, si tel est le cas, voici à peu près à quoi pourrait ressemble le code (qui ferait sensiblement la meme chose:
    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
    bool Usine::ajouterForme(const string& chaine, Forme* ptrF)
    {
    	Forme* ptrF2;
           /* la fonction dupliquer() fait, au minimum, un new ;) */
    	ptrF2=new Form(ptrF);
    	map<string, Forme*>::iterator it;
    	it= mymap.find(chaine);
    	if( it==mymap.end() )
    	{
                   /* pas de problème : mymap se charge de garder l'adresse 
                    * pointée par ptrF2
                    */
    		mymap.insert(pair<string, Forme*>(chaine,ptrF2));
    		return(1);
    	}
    	else
    	{
                    /* Ouuupsss... on perd toute référence à l'adresse pointée
                     * par ptrF2...
                     *
                     * Et on ne l'a pas libérée !!!!
                     * On fait cela trois millions de fois, et on explose le système 
                     * :D
                     */
    		return(0);
    	}
    }
    r
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

Discussions similaires

  1. Parcourir une map en fonction de deux critères
    Par lucares dans le forum Collection et Stream
    Réponses: 11
    Dernier message: 29/09/2011, 20h51
  2. Comment parcourir une map en sens inverse
    Par alen dans le forum SL & STL
    Réponses: 8
    Dernier message: 03/08/2008, 20h24
  3. créer et parcourir une map <int,list>
    Par GLSpirit dans le forum SL & STL
    Réponses: 6
    Dernier message: 10/05/2007, 14h59
  4. Réponses: 5
    Dernier message: 26/05/2005, 15h40
  5. problème de références _ptr dans une map STL
    Par Mr_Tyu dans le forum CORBA
    Réponses: 1
    Dernier message: 10/08/2004, 10h39

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