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 :

erreur de segmentation sur affectation champ enum structure


Sujet :

C

  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Février 2007
    Messages
    134
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 134
    Par défaut erreur de segmentation sur affectation champ enum structure
    Bonsoir,

    J'ai un joli segmentation fault qui me cause du file à retordre ! J'ai une structure qui contient un champ qui est une énumération. Lorsque je crée un objet du type de cet structure et que je donne une valeur à ce fameux champ, c'est le drame !! J'ai cherché sur internet quelques pistes sans succès !

    Voici le code concerné :

    Une partie de la structure avec l'enum qui pose problème :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
     
    typedef struct A_exp_ *A_exp;
     
    struct A_exp_ {
      enum {A_idExp, A_numEnt, A_chaine, A_numReel, A_expNeg, A_binExp, A_seqExp, A_suiteExp,A_fonction,A_compExp, A_bloc, A_affect, A_lvalue} sorte;
      union { 
        int entier;
        double reel;
      }u;
    };
    Le code qui crée une erreur de segmentation

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    
     A_exp *res=(A_exp *)malloc(sizeof(A_exp));
      if(res==0){
        printf("Erreur allocation id_exp\n");
        exit(1);
      }else{
        (*res)->sorte=A_idExp;  // ligne incriminée par gdb 
        (*res)->u.entier=i;
      }
      return *res;

  2. #2
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Chercheur d'emploi
    Inscrit en
    Septembre 2007
    Messages
    7 480
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur d'emploi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 480
    Par défaut
    Bonsoir,

    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    typedef struct A_exp_ *A_exp;

    Masquer un pointeur dans un typedef, c'est « mal ». C'est un modèle que l'on retrouve assez fréquemment dans les écoles, mais c'est toujours se créer des difficultés supplémentaires, surtout au déboguage.

    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     A_exp *res=(A_exp *)malloc(sizeof(A_exp));
    
        …
    
        (*res)->sorte=A_idExp;  // ligne incriminée par gdb 
        (*res)->u.entier=i;

    Et voila ! Quand tu fais « malloc(sizeof(A_exp)) », tu alloues non pas une structure mais un pointeur sur ta structure, celui-là même que tu as masqué avec ton typedef. Tu n'alloues donc que 4 octets en mémoire sur une machine 32 bits. Ta fonction malloc(), elle, te renvoie alors un « pointeur sur un pointeur sur une structure A_exp_ » (bien noter le « _ » final, abstrait lui aussi par le typedef).

    Ton pointeur, donc, est bien alloué en mémoire, mais n'est pas initialisé et ne pointe donc vers rien de valide (et pour cause, puisque la structure elle-même n'est toujours pas allouée). Les champs « sorte » et « u.entier » n'existent donc pas, et les valeurs que tu y déposes vont n'importe où en mémoire.

  3. #3
    Membre émérite
    Avatar de Pouet_forever
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    671
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2009
    Messages : 671
    Par défaut
    Pour tester le retour d'un malloc on utilise NULL et pas 0.

    Si tu veux retourner un pointeur tu n'as pas besoin de passer par un pointeur de pointeur, un simple pointeur suffit.

  4. #4
    Membre confirmé
    Profil pro
    Inscrit en
    Février 2007
    Messages
    134
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 134
    Par défaut
    whouh ! Merci pour l'explication ça fait plaisir une telle précision !
    Oui j'avoue tout, le système du pointeur dans typedef, c'est du code de mon école !
    J'ai bien compris l'histoire des allocations qui ne sont pas réellement faites mais j'avoue que je ne sais pas trop comment me dépatouiller ! Je vais tenter de m'expliquer : pour le reste de mon programme avec mon code actuel j'ai des fonctions qui renvoient des objets de type A_exp et pas A_exp* . Comment faire ?!

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

    Informations forums :
    Inscription : Février 2007
    Messages : 134
    Par défaut
    Alors j'ai simplifié mon problème, normalement j'utilise correctement les structures et les pointeurs comme j'ai déjà fait dans d'autres programmes auparavant ! Ca m'apprendra à travailler sur du code de mon école ... !
    Mais ce serait trop beau si ça marchait nikel ! J'ai un problème dans ma structure qui contient une structure et des champs du type de cette structure ! Un peu confus tout ça alors regardons 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
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    typedef struct A_value_ {
      enum {id, tab } type;
      union {
        str id;
        struct {
          str nom_tab;
          A_exp entre_croch;
        }tab;
      }u;
      int rang;
    }A_value;
    
    typedef struct A_exp_ {
      enum {A_idExp, A_numEnt, A_chaine, A_numReel, A_expNeg, A_binExp, A_seqExp, A_suiteExp,A_fonction,A_compExp, A_bloc, A_affect, A_lvalue} sorte;
      union { 
        A_value id; // message de gcc : erreur: expected specifier-qualifier-list before ‘A_value’
        str chaine;
        int entier;
        double reel;
        A_listExp seq;
        A_exp exp_neg;
        struct {
          A_value lvalue;
          A_exp val;
        }affect;
      }u;
    }A_exp;

  6. #6
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Chercheur d'emploi
    Inscrit en
    Septembre 2007
    Messages
    7 480
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur d'emploi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 480
    Par défaut
    Citation Envoyé par marion5515 Voir le message
    Mais ce serait trop beau si ça marchait nikel ! J'ai un problème dans ma structure qui contient une structure et des champs du type de cette structure ! Un peu confus tout ça alors regardons le code :
    Je n'arrive pas à reproduire l'erreur à la ligne exacte chez moi. Cela doit dépendre du reste de ton code. Par contre, il y a d'autres erreurs similaires :

    Code C : 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
    typedef struct A_value_ {
         …
        struct {
          str nom_tab;
          A_exp entre_croch; // A_exp n'est pas encore définie à ce stade.
        }tab;
      }u;
      int rang;
    }A_value;
    
    typedef struct A_exp_ {
        …
        double reel;
        A_listExp seq;
        A_exp exp_neg; // Une structure ne peut pas se contenir elle-même ! Par contre elle peut contenir un pointeur vers une autre instance.
        struct {
          A_value lvalue;
          A_exp val; // Même chose …
        }affect;
      }u;
    }A_exp;

  7. #7
    Expert confirmé
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Par défaut
    Tu vas avoir des problèmes : tes structures "s'auto-contiennent" directement ou indirectement ce qui est interdit :

    - A_value contient un A_exp qui contient plusieurs A_value (u.id et u.affect.lvalue)

    - A_exp contient plusieurs A_exp (u.exp_neg et u.affect.val) plus des A_value qui contiennent un A_exp

  8. #8
    Membre confirmé
    Profil pro
    Inscrit en
    Février 2007
    Messages
    134
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 134
    Par défaut
    Effectivement je ne peux que constater mon erreur d'autoinclusion mais j'ai besoin de cela !
    J'ai réussi à compiler en faisant quelques modifs mais je crains fortement avoir fait de la magouille qui n'est pas propre ! Et à vrai dire je ne comprends pas totalement pourquoi ceci passe sans problème !

    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
     
     
    typedef struct A_exp{
      enum {A_idExp, A_numEnt, A_chaine, A_numReel, A_expNeg, A_binExp, A_seqExp, A_suiteExp,A_fonction,A_compExp, A_bloc, A_affect, A_lvalue} sorte;
      union { 
        struct A_value *id;
        str chaine;
        int entier;
        double reel;
      }u;
    }A_exp;
     
    typedef struct A_value {
      enum {id, tab } type;
      union {
        str id;
        struct {
          str nom_tab;
          struct A_exp *entre_croch;
        }tab;
      }u;
      int rang;
    }A_value;

  9. #9
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Chercheur d'emploi
    Inscrit en
    Septembre 2007
    Messages
    7 480
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur d'emploi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 480
    Par défaut
    Citation Envoyé par marion5515 Voir le message
    Et à vrai dire je ne comprends pas totalement pourquoi ceci passe sans problème !
    Comme on l'a dit, tu ne peux pas déclarer une structure qui contient une instance d'elle-même, d'abord parce qu'à ce stade, elle n'est pas encore définie, ensuite parce qu'il en résulterait une structure d'une taille infinie : Si ta structure A contient un membre « m » qui est du même type, alors ce membre « m » doit lui aussi posséder un membre « m.m » qui, à son tour, serait doté d'un membre « m.m.m » et ainsi de suite.

    En revanche, tu peux très bien déclarer un pointeur vers une structure du même type, car cela n'implique pas de s'auto-contenir. Et c'est heureux car c'est nécessaire pour pouvoir monter une liste chaînée !

    En remplaçant les instances auto-contenues par des pointeurs, ton programme redevient légal. Par contre, la manière de les utiliser sera différente et, surtout, il faudra bien penser à les initialiser.

  10. #10
    Expert confirmé
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Par défaut
    J'ai l'impression que tu veux coder un genre d'interpréteur pour évaluer de façon récursive des expressions.
    Tu avais envisagé de placer la récursivité dans les structures de données, ce qui n'est pas possible, au lieu de la situer dans le code des fonctions.

    Pour illustrer symboliquement:
    Eval_Avalue(value) :
    si value du genre xx[yyy] , value.type = tab, value.tab.nom_tab = "xx", Eval_Aexp(yyy)...

Discussions similaires

  1. Erreur de segmentation sur une concaténation
    Par cypher.sephiroth dans le forum Débuter
    Réponses: 14
    Dernier message: 18/08/2009, 17h42
  2. Erreur de segmentation sur ifstream.close()
    Par tHE_fLAmMinG_mOE dans le forum SL & STL
    Réponses: 4
    Dernier message: 27/01/2009, 14h54
  3. Réponses: 8
    Dernier message: 13/11/2008, 21h28
  4. Erreur de segmentation sur une File
    Par hugo1992 dans le forum C
    Réponses: 2
    Dernier message: 22/10/2007, 08h49
  5. Erreur de segmentation sur une chaine en récursif...
    Par laurent_ifips dans le forum C
    Réponses: 12
    Dernier message: 13/12/2005, 16h04

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