Partage
  • Partager sur Facebook
  • Partager sur Twitter

Erreure Segmentation fault (core dumped)

    22 février 2018 à 21:03:04

    Bonsoir , 

    Je rencontre une erreur lors de l'execution du programme suivant , j'ai pu constaté que la fonction qui cause l'erreur a l’exécution est la fonction afiicherTransistion (dans transition.h && transition.cpp).

    Je ne sais pas quel est exactement la raison de segmentation fault .

    Tout aide serait grandement appréciée.

    Voici le code : 

    main.cpp

    #include "automate.h"
    #include "Etat.h"
    #include <iostream>
    using namespace std;
    
    int main(int argc, char const *argv[]) {
      cout << "Execution"<< endl;
      Automate automate1(18);
      char a = 'a';
      automate1.ajouterNouvelleTransition(0,1,'a');
      automate1.ajouterNouvelleTransition(1,3,'c');
    
      /*Etat test("ab");
      cout << test.getNom()<<endl;*/
      automate1.afficherEnsembleTransitions();
    
      return 0;
    }
    



    automate.h

    #ifndef AUTOMATE_H
    #define AUTOMATE_H
    
    #include "transition.h"
    #include "Etat.h"
    
    #include <stdlib.h>
    #include <vector>
    #include <iostream>
    
    /* Automate représenté sous forme de quintuplet
      A = alphabet
      Q = enseble des etats
      D = ensemble etats de dédepart
      F = ensemble des etats etatsFinaux
      T = ensembleDesTransitions
    
    */
    
    
    class Automate{
    private:
    char alphabet[5]={'a','b','c','d','e'};
    std::vector<Etat> ensembleGlobal;
    std::vector<Etat*> etatsFinaux;
    std::vector<Etat*> etatsInitiaux;
    std::vector<Transition> ensembleTransitions;
    public:
      Automate();
      Automate(int nbSalles);
    
      Etat transitionnement(const Etat &n, char a); // passe d'un etat donné a l'état le liant par l'etiquette de la fonction de transition
      void ajouterNouvelleTransition(int indiceDepart, int indiceArivee, char a);// ajoute une nouvelle transition a l'ensemle des transitions
    
      void afficherTransitionIndice(int n);// affiche la transition a l'indice n
      void afficherEnsembleTransitions(); // affiche l'ensemle des transitions
    
    };
    #endif

    automate.cpp

    #include "automate.h"
    
    using namespace std;
    
    Automate::Automate(){};
    
    Automate::Automate(int nbSalles){
      string a ="";
      for(int i=0;i<ensembleGlobal.size();i++){
        a =  to_string(i);
        ensembleGlobal[i]=Etat(a);
      }
    }
    
    
    Etat Automate::transitionnement(const Etat &n,char a){ // passe de l'etat actuel a un etat suivant si il y a une etiquette corresponddant a A se renvoi lui même sinon
      for (int i = 0 ;i<ensembleTransitions.size();i++){
        if(&n == ensembleTransitions[i].getEtatDepart() && a == ensembleTransitions[i].getEtiquette()){
          return *ensembleTransitions[i].getEtatArivee();
        }
      }
    }
    
    void Automate::ajouterNouvelleTransition(int indiceDepart, int indiceArivee, char a){
      Transition t(&ensembleGlobal[indiceDepart],&ensembleGlobal[indiceArivee],a);
      ensembleTransitions.push_back(t);
    }
    
    void Automate::afficherEnsembleTransitions(){
      for(int i=0;i<ensembleTransitions.size();i++){
        ensembleTransitions[i].afficherTransition();
      }
    }
    
    void Automate::afficherTransitionIndice(int n){
      ensembleTransitions.at(n).afficherTransition();
    }
    

    Transition.h

    #ifndef TRANSITION_H
    #define TRANSITION_H
    
    //class Etat;
    #include "Etat.h"
    
    /* Structure de donnée représantant la transition */
    class Transition{
    private:
      Etat* depart;
      char etiquette;
      Etat* arrivee;
    
    public:
      //Constructeur
      Transition(Etat* EtatDepart, Etat* etatArivee, char a);
    
      //Accesseurs
      char getEtiquette();
      Etat* getEtatDepart();
      Etat* getEtatArivee();
    
      //Setteurs
      void setEtiquette(char a);
      void setEtatDepart(Etat* depart);
      void setEtatArivee(Etat* arivee);
    
      // LE PROBLEME
      void afficherTransition();
    
    };
    
    #endif
    

    transition.cpp

    #include "transition.h"
    using namespace std;
    
    Transition::Transition(Etat* EtatDepart, Etat* etatArivee, char a): depart(EtatDepart),arrivee(etatArivee),etiquette(a){};
    
    void Transition::setEtiquette(char a){
      etiquette = a;
    }
    char Transition::getEtiquette(){
      return etiquette;
    }
    Etat* Transition::getEtatDepart(){
      return depart;
    }
    Etat* Transition::getEtatArivee(){
      return arrivee;
    }
    
    void Transition::setEtatDepart(Etat* depart){
      depart = depart;
    }
    
    void Transition::setEtatArivee(Etat* arivee){
      arivee =arivee;
    }
    
    
    void Transition::afficherTransition(){
      cout << depart->getNom() << etiquette << arrivee->getNom() << endl;
    }
    

    Etat.h

    #ifndef ETAT_H
    #define ETAT_H
    
    //class Transition;
    #include <iostream>
    #include <string>
    //#include "transition.h"
    
    
    
    class Etat{
    private:
      std::string nom;
    public:
      Etat(std::string nom);
      
      void setNom(std::string a);
      std::string getNom();
    };
    
    #endif
    

    Etat.cpp

    #include "Etat.h"
    using namespace std;
    
    Etat::Etat(string nom):nom(nom){};
    
    void Etat::setNom(std::string a){
      this->nom = a;
    }
    
    string Etat::getNom(){
      return nom;
    }
    









    • Partager sur Facebook
    • Partager sur Twitter
      22 février 2018 à 22:57:21

      Bonjour,

      Les erreurs de segmentation (Segmentation fault) sont causées par l'accès à un endroit de la mémoire qui ne t'appartient pas. Cela peut être le déférencement du pointeur NULL, l'utilisation d'un pointeur après delete ou le fait de sortir d'un tableau.

      Il faut bien noter que par défaut les std::vector sont vides. Ainsi, si dans ta classe Automate tu n'augmentes pas la taille de 'ensembleGlobal', cette dernière restera à 0. Et justement, tu n'augmentes jamais la taille de ce dernier. Ainsi, quelque soit les indices que tu passes à la fonction 'ajouterNouvelleTransition', '&ensembleGlobal[indice]' est en dehors du tableau: tu accèdes donc à de la mémoire de n'appartenant pas lorsque tu essayes d'utiliser la variable 'depart' de ta classe 'Transition' ce qui cause l'erreur de segmentation.

      Je n'ai pas regardé en détail le code (cela implique que le correctif proposé n'a peut être pas de sens pour l'utilisation que tu veux, cependant il en a dans le contexte du constructeur), mais, en changeant le constructeur de Automate comme suivant, la sortie est (et sans erreur de segmentation):

      Execution

      0a1

      1c3

      Automate::Automate(int nbSalles){
        string a ="";
        for(int i=0;i<nbSalles;i++){ //ensembleGlobal.size() vaut 0 et donc tu ne rentrais jamais dans cette boucle
          a =  to_string(i);
          ensembleGlobal.emplace_back(a); //ensembleGlobal[i]=Etat(a); Aurait causer une erreur de segmentation.
                                          //emplace_back augmente la taille du tableau tout comme push_back le fait, 
                                          //la différence étant que emplace_back ne crée pas de copie supplémentaire
                                          //de l'objet à insérer
      
        }
      }
      

      Je m'excuses pour les éventuelles fautes d'orthographe.

      En espérant avoir été clair,

      Cordialement,

      Sacrefeu

      -
      Edité par sacrefeu69 22 février 2018 à 23:00:23

      • Partager sur Facebook
      • Partager sur Twitter
        23 février 2018 à 13:48:51

        @Sacrefeu , 

        Merci beaucoup pour ton aide ! le programme marche et compile parfaitement maintenant :)

        • Partager sur Facebook
        • Partager sur Twitter
          23 février 2018 à 14:23:56

          Salut  Mec 

          je crains que ton code fonctionne parfaitement ex:

          Transition::Transition(Etat* EtatDepart, Etat* etatArivee, char a): depart(EtatDepart),arrivee(etatArivee),etiquette(a){};

          ici ton constructeur attend deux pointeur du type Etat (EtatDepart et etatArivee) mais toi, tu initialise très mal tes attribut (depart et arrivee) qui sont de pointeurs et aussi des objet du type Etat; or pour initialiser un objet qui est un pointeur on utilise l'opérateur " new ".

          2ième erreur:

          void Transition::setEtatDepart(Etat* depart){
            depart = depart;
          }
           
          void Transition::setEtatArivee(Etat* arivee){
            arivee =arivee;
          }

          pour modifier des pointeur qui sont du type objet, on utilise toujours l' opérateur  " new". 

          donc tu dois faire:

           pointeur = new constructeur(nouveau pointeur);






          • Partager sur Facebook
          • Partager sur Twitter

          Ton présent détermine ton futur et la connaissance te placera au dessus de ta génération .

            23 février 2018 à 14:48:30

            @El-jos : non et non. Ce que tu raconte est absolument faux.

            New sert a allouer de la memoire, pas a modifier des pointeurs... Son code peux par contre poser certains problemes de part l usage de pointeurs nus

            • Partager sur Facebook
            • Partager sur Twitter
              23 février 2018 à 14:56:10

              @Elried: en parlant de modifier, je faisais allusion à ceci:

              new: alloue la mémoire puis l'opérateur " = " le stocke dans le pointeur, donc l'ancienne adresse(valeur) contenue dans le pointeur sera écrasé.

              donc la valeur du pointeur est modifié.  

              • Partager sur Facebook
              • Partager sur Twitter

              Ton présent détermine ton futur et la connaissance te placera au dessus de ta génération .

                23 février 2018 à 15:20:14

                Certes... Mais on utilise pas toujours nes pour modifier un pointeur (meme un pointeur vers un objet) et la facon (sans new) dont il gere son constructeur semble correcte.

                J'ai l'impression que tu confond allouer un espace memoire et initialiser un pointeur...

                • Partager sur Facebook
                • Partager sur Twitter
                  23 février 2018 à 15:30:52

                  ah bon d'accord
                  • Partager sur Facebook
                  • Partager sur Twitter

                  Ton présent détermine ton futur et la connaissance te placera au dessus de ta génération .

                    24 février 2018 à 14:25:44

                    Et on utilise jamais new en C++, à moins de très bien savoir ce qu'on fait. Utilisez des pointeurs intelligents.

                    • Partager sur Facebook
                    • Partager sur Twitter

                    Posez vos questions ou discutez informatique, sur le Discord NaN | Tuto : Preuve de programmes C

                    Erreure Segmentation fault (core dumped)

                    × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                    × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                    • Editeur
                    • Markdown