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 :

Problème segfault copie de map


Sujet :

Langage C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre habitué
    Inscrit en
    Mai 2009
    Messages
    10
    Détails du profil
    Informations forums :
    Inscription : Mai 2009
    Messages : 10
    Par défaut Problème segfault copie de map
    Bonjour,

    je rencontre un problème de segmentation fault que je ne comprend pas.

    J'ai la structure suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    typedef struct _dbus_order{
    	int 				nUserId;
    	int 				nChannelId;
    	std::map < int , int  > mapArticlesId;
    }dbus_order;
    Et je m'en sert comme ca :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    dbus_order *pData = (dbus_order *)malloc(sizeof(pData));
    std::map < int , int > mapTmp;
    for(unsigned int i=0 ; i < p_basket->getList().size() ; i++){
    mapTmp.insert(std::pair<int , int>(p_basket->getList()[i].id , p_basket->getList()[i].quantity));
    }
    pData->mapArticlesId = mapTmp;
    La suite n'a pas d'importance.
    et la copie (derniere ligne) me crée une erreur de segmentation.
    J'ai essayé aussi :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    pData->mapArticlesId.insert(mapTmp.begin(), mapTmp.end());
    mais meme résultat.

    merci d'avance pour votre aide

  2. #2
    Membre expérimenté Avatar de Nogane
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    241
    Détails du profil
    Informations personnelles :
    Âge : 45
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 241
    Par défaut
    Bonjour,
    Voila le problème:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    dbus_order *pData = (dbus_order *)malloc(sizeof(pData));
    Cette ligne alloue bien a zone mémoire pour le dbus_order, mais n'appel pas le constructeur de pData. Ce qui fait que pData n'est pas construit.
    C'est pourquoi en c++ on utilise new au lieu de malloc, qui a le double emploie de faire une allocation ET une construction.
    Essayez avec:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    dbus_order *pData = new dbus_order();
    Ce qui vous évite, en plus de faire un cast 'c-style' (ou 'a la C', comme disent les anglophones)

    Remarquez que si vous n'avez pas de bonne raison de passer par un pointeur, il est encore mieux de s'en passer:

  3. #3
    Membre habitué
    Inscrit en
    Mai 2009
    Messages
    10
    Détails du profil
    Informations forums :
    Inscription : Mai 2009
    Messages : 10
    Par défaut
    Merci mille fois !

    En effet j'ai fait pas mal de C mais je débute en C++.


    Dans mon esprit l'opérateur new n'était applicable qu'a un objet et non a une simple structure.

    merci encore

  4. #4
    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, et bienvenue sur le forum.

    Je ne voudrait pas que cette remarque passe pour agresseive, mais... y a de la place pour le progès
    Citation Envoyé par kashikai Voir le message
    Bonjour,

    je rencontre un problème de segmentation fault que je ne comprend pas.

    J'ai la structure suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    typedef struct _dbus_order{
    	int 				nUserId;
    	int 				nChannelId;
    	std::map < int , int  > mapArticlesId;
    }dbus_order;
    Contrairement à C, la définition d'une classe, d'une structure ou d'une union entraine automatiquement la définition du type correspondant...

    Tu peux donc parfaitement te contenter d'un
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    struct dbus_order
    {
    	int 				nUserId;
    	int 				nChannelId;
    	std::map < int , int  > mapArticlesId;
    };
    Comme std::map est une classe, il ne sera pas possible de travailler en C avec une telle structure (du moins en l'état), et tu ne dois donc pas t'inquiéter d'assurer une quelconque compatibilité avec ce langage
    Et je m'en sert comme ca :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    dbus_order *pData = (dbus_order *)malloc(sizeof(pData));
    std::map < int , int > mapTmp;
    for(unsigned int i=0 ; i < p_basket->getList().size() ; i++){
    mapTmp.insert(std::pair<int , int>(p_basket->getList()[i].id , p_basket->getList()[i].quantity));
    }
    pData->mapArticlesId = mapTmp;
    La suite n'a pas d'importance.
    et la copie (derniere ligne) me crée une erreur de segmentation.
    J'ai essayé aussi :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    pData->mapArticlesId.insert(mapTmp.begin(), mapTmp.end());
    Primo : pourquoi utiliser un pointeur et l'allocation dynamique
    Je ne dis pas que ce n'est pas intéressant dans ton cas, mais, d'expérience je peux t'assurer que, s'il n'est pas question que ta variable survive à la portée dans laquelle elle est déclarée, il est beaucoup plus facile de se passer de l'allocation dynamique.

    De plus, pourquoi diable t'enquiquiner à remplir une std::map temporaire pour en copier le contenu dans la structure ou pour afecter cette map temporaire à celle de la structure pourquoi ne pas directement insérer les éléments... là où tu en aura besoin :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    dbus_order data;
    for(unsigned int i=0 ; i < p_basket->getList().size() ; i++){
        data.mapArticleId.insert( std::pair<int , int>(
                  p_basket->getList()[i].id , p_basket->getList()[i].quantity));
    }
    serait beaucoup plus facile.

    Secundo: Si tu as de bonnes raisons d'avoir recours aux pointeurs et à l'allocation dynamique (ce qui peut malgré tout arriver ), il vaut mieux abandonner les fonction malloc, calloc et autres *alloc issues du C au profit de new.

    En effet, les fonctions C *alloc ne font que... réserver un espace mémoire de la taille indiquée alors que new:
    1. a une syntaxe beaucoup plus facile : dbus_order * ptr = new dbus_order;
    2. fait quelques trucs en plus, comme appeler le constructeur de ta structure et affecter effectivement chaque partie de la mémoire au membre correspondant

    En utilisant un pointeur, nous aurions donc:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    dbus_order * pdata = new dbus_order;
    for(unsigned int i=0 ; i < p_basket->getList().size() ; i++){
        data->mapArticleId.insert( std::pair<int , int>(
                  p_basket->getList()[i].id , p_basket->getList()[i].quantity));
    }
    Tertio : A moins qu'il n'y ait de sérieuses raisons de tout laisser visible, il serait sans doute préférable d'encapsuler un peu tous ces détails d'implémentation...

    C++ est un langage (entre autre) orienté objet: autant en profiter:

    Il serait donc peut être intéressant d'envisager de transformer ta structure en classe avec tout ce que cela implique sous une forme proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    class dbus_order{
        public:
            dbus_order(int user, int chan):nUserId(user),nChannelId(chan){}
            int userId() const{return nUserId;}
            int channelId() const{return nChannelId;}
            void addArticles(int key, int value)
            {
                mapArticlesId.insert(std::make_pair(key,value);
            }
        private:
            int nUserId;
            int  nChannelId;
            std::map < int , int  > mapArticlesId;
    };
    qui serait remplie sous la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    dbus_order data(idUser, idChannel);
    for(unsigned int i=0 ; i < p_basket->getList().size() ; i++){
        data.addArticles(p_basket->getList()[i].id , 
                        p_basket->getList()[i].quantity));
    }
    Cela te permettra entre autres, pour autant que tu garde le même prototype pour addArticles, de décider "n'importe quand" de changer la manière dont tes articles sont gardés en mémoire

    [EDIT]Enfin, ce n'est qu'un détail, mais je ne suis absolument persuadé de l'opportunité d'avoir défini une fonction getListe dans la classe don p_basket est un digne représentant...

    Je ne peux, bien sur, que faire des suppositions, mais il semblerait que getList renvoie... un std::vector contenant une structure quelconque.

    Si c'est le cas, il serait des plus intéressant de remplacer cette fonction par:
    1. la définition (dans la classe) d'un alias de type proche de std::vector<la_structure>::const_iterator const_iterator;
    2. la définition d'une fonction begin() renvoyant l'itérateur sur la_liste.begin();
    3. la définition d'une fonction end() renvoyant l'itérateur sur la_liste.end();
    (le tout en accessibilité publique).

    Le code pourrait alors être modifié sous la forme de
    d
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    bus_order data(idUser, idChannel);
    for(LaClass::const_iterator  it=p_basket->begn(), ; it != p_basket->end() ; ++it){
        data.addArticles( (*it).id, (*it).quantity);
    }
    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

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

Discussions similaires

  1. [VBA-E] Problème de copie de données
    Par JM_stp dans le forum Macros et VBA Excel
    Réponses: 3
    Dernier message: 25/02/2006, 00h33
  2. [VB]Problème de copie
    Par sterepathie dans le forum VB 6 et antérieur
    Réponses: 27
    Dernier message: 26/01/2006, 17h10
  3. [XSL] problème avec copy espace de nom
    Par luta dans le forum XSL/XSLT/XPATH
    Réponses: 1
    Dernier message: 11/10/2005, 15h18
  4. Problème de copie de string dans string
    Par kazarn dans le forum SL & STL
    Réponses: 17
    Dernier message: 15/03/2005, 18h35

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