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 :

Deux méthodes similaires et segmentation fault


Sujet :

C++

  1. #1
    Futur Membre du Club
    Femme Profil pro
    Étudiant
    Inscrit en
    Octobre 2016
    Messages
    9
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 31
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Octobre 2016
    Messages : 9
    Points : 6
    Points
    6
    Par défaut Deux méthodes similaires et segmentation fault
    Bonjour à tous

    Mon cerveau est en train d'exploser à cause de ce problème ^^

    J'ai une classe Rule dont voici les attributs :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    class Rule
    {
        std::vector<std::string> m_answers;
        std::vector<int> m_numAnswers;
        std::vector<int> m_answersType;
        std::vector<std::string> m_involvedWords;
        int m_numCombination;
        std::map<std::vector<std::string>, Rule*> m_followingRules;  // C'est celui-là qui nous intéresse
        int m_lineNumber;
        Rule* m_motherRule;
    }
    Cette classe a plusieurs méthodes, dont deux très similaires :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    void Rule::addFollowingRule(Rule* newFollowingRule) // Ajoute une followingRule
    {
        m_followingRules.insert(make_pair(newFollowingRule->getInvolvedWords(), newFollowingRule));
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    bool Rule::changeFollowingRule(Rule* newRule) // Remplace une followingRule existante
    {
        vector<string> keywords = newRule->getInvolvedWords();
        Rule* precedentRule = m_followingRules[keywords];
        m_followingRules[keywords] = newRule;
        delete precedentRule;
        return 1;
    }
    Dans la fonction qui les utilise, on a :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    if(replacement)
        {
            ok = motherRule->changeFollowingRule(newRule);
            if(!ok) return 0;
        }
    else motherRule->addFollowingRule(newRule);
    Le code se compile sans erreur ni warning.
    Dans le cas où replacement = 0, on exécute addFollowingRule sur motherRule, tout vas bien, sans problème. Dans le cas où replacement = 1, quelque soit la manipulation de m_followingRules que je fais dedans, j'ai un segmentation fault.
    Même si je change ma fonction pour :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    bool Rule::changeFollowingRule(Rule* newRule) // Remplace une followingRule existante
    {
        int a = m_followingRules.size();
        return 1;
    }
    Je ne comprends vraiment pas ce qui se passe, il n'y a pas du tout de problèmes dans les autres méthodes de la classe Rule. C'est sûrement un truc très bête mais je n'arrive pas à le voir. Merci d'avance pour votre aide !

  2. #2
    Rédacteur/Modérateur


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

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 967
    Points
    32 967
    Billets dans le blog
    4
    Par défaut
    Salut,

    Passé le choc de voir un std::vector<std::string> en clé de map , si ça crash, le debugger doit t'en dire plus.
    Sans aller bien loin, ceci est plus que suspect:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    bool Rule::changeFollowingRule(Rule* newRule) // Remplace une followingRule existante
    {
        vector<string> keywords = newRule->getInvolvedWords();
        Rule* precedentRule = m_followingRules[keywords];
        m_followingRules[keywords] = newRule;
        delete precedentRule;
        return 1;
    }
    Tu delete un truc, sans t'assurer que ça existe bien.
    Ca n'a peut-être rien à voir, mais c'est très pas propre.

    Et faire un return 1 alors que ta fonction est un bool.. true false ?
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  3. #3
    Membre éprouvé
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    780
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Mai 2006
    Messages : 780
    Points : 1 176
    Points
    1 176
    Par défaut
    Au hasard, enlève tes pointeurs? Remplace les par des shared_ptr ou par des valeurs?

  4. #4
    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
    Citation Envoyé par Bousk Voir le message
    Tu delete un truc, sans t'assurer que ça existe bien.
    Il n'y a pas de soucis ici : si l'élément n'existe pas dans la map, l'opérateur [] retournera nullptr, et on a le droit de faire delete d'un nullptr.

    Pour le problème initial, on n'a pas vraiment assez de code pour se prononcer. Il manque en particulier le code appelant.

    De base, j'ai l'impression que la gestion des durées de vie est assez floue. La question est : Qui possède les Rules ? On dirait que c'est la map qui les possède, puisque quand on enlève un élément de la map, on delete la Rule. Sauf que quand on ajoute un élément dans la map, si cet ajout échoue, on ne fait rien de la Rule qu'on a tenté d'insérer, et qui risque donc d'être perdue. Je pense que la solution passe donc par une clarification des durées de vie/possessions des objets.

    Comme l'a dit nikko34, le C++ possède des outils pour aider à gérer ça. Si tu ne peux utiliser des valeurs, essaye d'utiliser des std::unique_ptr à la place (les std::shared_ptr ont parfois leur rôle à jouer, mais je ne suis pas convaincu que ce soit le cas ici. Et en tout cas commencer avec des unique_ptr aura comme avantage de clarifier les responsabilités). Si tu ne les as pas encore étudiés dans ton apprentissage, ce 'nest pas grave, essaye déjà de résoudre ton problème sans ça. Puis étudie les et résoud ton problème à nouveau mais en les utilisant, et tu verras alors en quoi ils peuvent t'aider.
    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.

  5. #5
    Futur Membre du Club
    Femme Profil pro
    Étudiant
    Inscrit en
    Octobre 2016
    Messages
    9
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 31
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Octobre 2016
    Messages : 9
    Points : 6
    Points
    6
    Par défaut
    Les Rules sont stockées dans un dictionnaire, et chaque Rule peut mener à une ou plusieurs Rules suivantes (followingRules), ce qui fait que l'ensemble des Rules est organisé en arbre. Le dico contient les Rules primaires dans la map m_primRulesList, chacune d'entre elles pouvant mener à d'autres Rules, donc chaque Rule primaire est la racine d'un arbre de Rule, si on veut.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    class Dico
    {
        // Attributes
        [..]
        std::map<std::vector<std::string>, Rule*> m_primRulesList;

    Ce que je ne comprends pas, c'est que je peux manipuler l'attribut followingRules dans d'autres méthodes de la classe (méthode addFollowingRule) mais pas dans cette méthode changeFollowingRule, même si je me contente juste de demander la taille de followingRules.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    void Rule::changeFollowingRule(Rule* newRule) // Remplace une followingRule existante
    {
        int a = m_followingRules.size();
    }
    Concernant la vérification de l'insertion de l'élément dans la map, tu as raison, je vais le faire. Mais je suis certaine que les Rules sont bien insérées, j'ai testé mon programme et tout fonctionne très bien, les Rules ajoutées font bien leur boulot et sont bien ajoutées au bon endroit. Voilà une autre version de la fonction qui teste si la Rule à changer existe bien avant de le faire (ça ne marche toujours pas).
    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
     
    bool Rule::changeFollowingRule(Rule* newRule)
    {
        vector<string> keywords = newRule->getInvolvedWords();
    //    cout<<"word : "<<keywords[0]<<endl;
    //    cout<<"size : "<<int2str(m_followingRules.size())<<endl;
        map<vector<string>, Rule*>::iterator it;
        it = m_followingRules.find(keywords);
        if(it!=m_followingRules.end())
        {
            Rule* precedentRule = it->second;
            m_followingRules[keywords] = newRule;
            delete precedentRule;
            return true;
        }
        else
        {
            cout<<"The rule could not be deleted."<<endl;
            return false;
        }
    }
    Je suis désolée, le reste de mon code est vraiment complexe (ce n'est pas un exercice, je suis en stage), et je ne suis pas sûre d'avoir le droit de poster beaucoup de code. On m'a servi tout une tartine sur les droits de l'université sur mon travail...

    PS : je n'ai jamais utilisé les unique_ptr, je vais regarder

  6. #6
    Futur Membre du Club
    Femme Profil pro
    Étudiant
    Inscrit en
    Octobre 2016
    Messages
    9
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 31
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Octobre 2016
    Messages : 9
    Points : 6
    Points
    6
    Par défaut
    Citation Envoyé par Bousk Voir le message
    Salut,

    Passé le choc de voir un std::vector<std::string> en clé de map , si ça crash, le debugger doit t'en dire plus.
    Sans aller bien loin, ceci est plus que suspect:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    bool Rule::changeFollowingRule(Rule* newRule) // Remplace une followingRule existante
    {
        vector<string> keywords = newRule->getInvolvedWords();
        Rule* precedentRule = m_followingRules[keywords];
        m_followingRules[keywords] = newRule;
        delete precedentRule;
        return 1;
    }
    Tu delete un truc, sans t'assurer que ça existe bien.
    Ca n'a peut-être rien à voir, mais c'est très pas propre.

    Et faire un return 1 alors que ta fonction est un bool.. true false ?
    Je ne vois pas vraiment en quoi c'est choquant ^^ c'est très efficace dans mon code, et jusque-là ça marchait très bien. La fonction changeFollowingRule n'est que mon dernier ajout au programme. Le debugger me fait un segmentation fault dès que je rentre dans la fonction et que je touche de près ou de loin à m_followingRules...

  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
    Citation Envoyé par Salamandre92 Voir le message
    Les Rules sont stockées dans un dictionnaire, et chaque Rule peut mener à une ou plusieurs Rules suivantes (followingRules), ce qui fait que l'ensemble des Rules est organisé en arbre. Le dico contient les Rules primaires dans la map m_primRulesList, chacune d'entre elles pouvant mener à d'autres Rules, donc chaque Rule primaire est la racine d'un arbre de Rule, si on veut.
    Si j'essaye de traduire ç en C++ moderne, je dirais que primRulesList est une map de unique_ptr<Rule>, et que dans chaque Rule, followingRules est une map de unique_ptr<Rule>. Par contre, m_motherRule est un pointeur nu, qui ne possède pas la Rule pointée..

    Citation Envoyé par Salamandre92 Voir le message
    Ce que je ne comprends pas, c'est que je peux manipuler l'attribut followingRules dans d'autres méthodes de la classe (méthode addFollowingRule) mais pas dans cette méthode changeFollowingRule, même si je me contente juste de demander la taille de followingRules.
    Généralement, quand ce genre de choses arrive, ce n'est pas la donnée membre qui a un soucis, c'est l'objet lui même auquel elle appartient. Par exemple, si tu appelles cette fonction sur un objet qui a déjà été détruit, tu auras ce genre de problème. C'est pour ça que je disais que pour déboguer, il nous faudrait voir plus de code.

    Citation Envoyé par Salamandre92 Voir le message
    Je suis désolée, le reste de mon code est vraiment complexe (ce n'est pas un exercice, je suis en stage), et je ne suis pas sûre d'avoir le droit de poster beaucoup de code. On m'a servi tout une tartine sur les droits de l'université sur mon travail...
    Et si tu postais trop, personne ne le lirait, de toute façon...
    Ma question est plutôt la suivante : Est-ce que tu arrives à reproduire ce problème sur un cas de test unitaire, découpé de ton véritable code ? Si oui, tu dois pouvoir reproduire ici cet exemple réduit. Genre tu crées un main qui crée 2 ou 3 Rules, les assemble, essaye d'en ajouter une, vérifie qu'elle est bien dedans...
    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
    Futur Membre du Club
    Femme Profil pro
    Étudiant
    Inscrit en
    Octobre 2016
    Messages
    9
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 31
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Octobre 2016
    Messages : 9
    Points : 6
    Points
    6
    Par défaut
    Citation Envoyé par JolyLoic Voir le message


    Et si tu postais trop, personne ne le lirait, de toute façon...
    Ma question est plutôt la suivante : Est-ce que tu arrives à reproduire ce problème sur un cas de test unitaire, découpé de ton véritable code ? Si oui, tu dois pouvoir reproduire ici cet exemple réduit. Genre tu crées un main qui crée 2 ou 3 Rules, les assemble, essaye d'en ajouter une, vérifie qu'elle est bien dedans...
    Merci, j'ai suivi ta méthode, ma fonction marche avec un code simple. J'y ai passé le week-end mais j'ai compris pourquoi elle ne fonctionnait pas : dans certains cas, motherRule pointait vers l'adresse nulle.

    Merci de votre patience en tous cas !

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

Discussions similaires

  1. Pb segmentation fault avec glutinit()
    Par pipistrelle dans le forum GLUT
    Réponses: 2
    Dernier message: 17/11/2004, 23h17
  2. [SDL_Image] Img_Load : segmentation fault ....
    Par Mathieu.J dans le forum OpenGL
    Réponses: 6
    Dernier message: 19/10/2004, 23h52
  3. [REDHAT] Segmentation fault systematique
    Par mela dans le forum RedHat / CentOS / Fedora
    Réponses: 2
    Dernier message: 21/09/2004, 06h05
  4. Réponses: 13
    Dernier message: 13/07/2004, 15h41
  5. Comment contrer la "segmentation fault" ?
    Par guillaume_pfr dans le forum C
    Réponses: 15
    Dernier message: 08/08/2003, 13h43

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