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 en utilisant la fonction free


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Homme Profil pro
    Statistique
    Inscrit en
    Octobre 2014
    Messages
    33
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Jura (Franche Comté)

    Informations professionnelles :
    Activité : Statistique

    Informations forums :
    Inscription : Octobre 2014
    Messages : 33
    Par défaut Erreur de segmentation en utilisant la fonction free
    Bonjour.

    J’ai une erreur de segmentation en utilisant la fonction free que je ne parviens pas à comprendre.
    L’erreur disparaît si je supprime l’instruction free(self->states);
    J’ai épuré le code pour ne garder que les éléments liés à l’erreur.

    Mon output est précisément
    Coucou 1
    Coucou 2
    Erreur de segmentation (core dumped)

    Quelqu’un comprend-t-il mon erreur?

    Merci.


    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
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
     
    #include <stdio.h>
    #include <stdlib.h>
    #include <stdbool.h>
    //#include "fa.h"
     
     
    struct fa
    {
    	struct state *states; //Tableau des états composant l'automate	
    };
     
     
    struct state
    {
    	//Chaque état, peut être final et/ou initial
    	bool is_initial;
    	bool is_final;
    };
     
     
    void fa_create(struct fa *self, size_t alpha_count, size_t state_count)
    {
    	self = malloc(sizeof(struct fa*));
    	self->states = calloc(state_count, sizeof(struct state*));	
    }
     
     
    void fa_destroy(struct fa *self)
    {
    	free(self->states); // L'erreur disparait si je commente cela...
    	free(self);
    }
     
     
    int main()
    {
    struct fa *autom=NULL;
    printf("Coucou 1 \n");
    fa_create(autom, 3, 5);
    printf("Coucou 2 \n");
    fa_destroy(autom);
    printf("Coucou 3 \n");
    }

  2. #2
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 452
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 452
    Par défaut
    Bonjour,

    Ici :

    Citation Envoyé par Obofix le gaulois Voir le message

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    void fa_create(struct fa *self, size_t alpha_count, size_t state_count)
    {
    	self = malloc(sizeof(struct fa*));
    	self->states = calloc(state_count, sizeof(struct state*));	
    }
    Tu alloues suffisamment d'espace non pas pour une structure fa (reférencée par un « pointeur sur une structure fa » que tu as ici nommé self) mais pour un « pointeur sur une structure fa », soit 4 ou 8 octets uniquement.

    Quand tu l'exploites, tu fais un dépassement de segment mais comme tout cela reste à l'intérieur du segment alloué à ton processus, le micro-processeur ne déclenche pas de segfault. Il reste que tu corromps sans le savoir tes données adjacentes, et le crash se produit a posteriori, au moment de libérer la mémoire.

  3. #3
    Membre averti
    Homme Profil pro
    Statistique
    Inscrit en
    Octobre 2014
    Messages
    33
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Jura (Franche Comté)

    Informations professionnelles :
    Activité : Statistique

    Informations forums :
    Inscription : Octobre 2014
    Messages : 33
    Par défaut
    Effectivement vous avez raison.

    En revanche je dois avoir une autre erreur car même en retirant l’étoile de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    self = malloc(sizeof(struct fa*));
    j’ai de toujours 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
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
     
    #include <stdio.h>
    #include <stdlib.h>
    #include <stdbool.h>
    //#include "fa.h"
     
    struct fa
    {
    	struct state *states; //Tableau des états composant l'automate	
    };
     
     
    struct state
    {
    	//Chaque état, peut être final et/ou initial
    	bool is_initial;
    	bool is_final;
    };
     
     
    void fa_create(struct fa *self, size_t alpha_count, size_t state_count)
    {
    	self = malloc(sizeof(struct fa));
    	self->states = calloc(state_count, sizeof(struct state*));	
    }
     
     
    void fa_destroy(struct fa *self)
    {
    	free(self->states); // L'erreur disparait si je commente cela...
    	free(self);
    }
     
     
     
    int main()
    {
    struct fa *autom=NULL;
    printf("Coucou 1 \n");
    fa_create(autom, 3, 5);
    printf("Coucou 2 \n");
    fa_destroy(autom);
    printf("Coucou 3 \n");
    }

  4. #4
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 393
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 393
    Par défaut
    Bonjour,
    Il y a deux problèmes.
    1. Même erreur sur states.
      Sinon plutôt que faire un sizeof du type, tu peux utiliser l'écriture alternative "sizeof du type pointé":
      Code C : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      5
      void fa_create(struct fa *self, size_t alpha_count, size_t state_count)
      {
      	self = malloc(sizeof(*self));
      	self->states = calloc(state_count, sizeof(self->states[0]));	
      }
    2. Ton appel de fonction est incorrect: Ta fonction est censée modifier le pointeur self, mais ne reçoit en paramètre qu'une copie de celle-ci. Pour corriger ça, soit tu retourne la variable:
      Code C : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      5
      6
      struct fa * fa_create(size_t alpha_count, size_t state_count)
      {
      	struct fa * self = malloc(sizeof(*self));
      	self->states = calloc(state_count, sizeof(self->states[0]));	
      	return self;
      }
      Soit tu utilises un pointeur de pointeur:
      Code C : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      5
      6
      void fa_create(struct fa **ppself, size_t alpha_count, size_t state_count)
      {
      	struct fa *self = malloc(sizeof(*self));
      	*self->states = calloc(state_count, sizeof(self->states[0]));	
      	*ppself = self;
      }
      N'oublie pas de modifier l'appel en conséquence.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  5. #5
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 815
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 815
    Billets dans le blog
    1
    Par défaut
    Bonjour
    Citation Envoyé par Médinoc Voir le message
    Pour corriger ça, soit tu retourne la variable:
    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    void fa_create(size_t alpha_count, size_t state_count)
    {
    	struct fa * self = malloc(sizeof(*self));
    	self->states = calloc(state_count, sizeof(self->states[0]));	
    	return self;
    }
    et ne pas oublier de faire correspondre le type de la fonction en conséquence...
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  6. #6
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 393
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 393
    Par défaut
    OK, c'est corrigé.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  7. #7
    Membre averti
    Homme Profil pro
    Statistique
    Inscrit en
    Octobre 2014
    Messages
    33
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Jura (Franche Comté)

    Informations professionnelles :
    Activité : Statistique

    Informations forums :
    Inscription : Octobre 2014
    Messages : 33
    Par défaut
    Citation Envoyé par Médinoc Voir le message
    [*]Ton appel de fonction est incorrect: Ta fonction est censée modifier le pointeur self, mais ne reçoit en paramètre qu'une copie de celle-ci. Pour corriger ça, soit tu retourne la variable:
    Je viens de comprendre que calloc modifie la valeur du pointeur.

    Dans ma tête calloc «affectait de la mémoire au pointeur mais sans le modifier». Ce qui n’a probablement aucun sens. Les choses sont plus claires maintenant.

    Merci à tous les répondants. :-)

  8. #8
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 815
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 815
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Obofix le gaulois Voir le message
    Je viens de comprendre que calloc modifie la valeur du pointeur.
    Là je ne suis pas certain de bien comprendre. calloc ne peut en aucun cas modifier la valeur du pointeur (duquel d'ailleurs puisque cette fonction ne reçoit pas de pointeur en paramètre !!!!!!!)
    calloc alloue une zone mémoire et remplit cette zone de zéros. Ce n'est pas exactement la même chose...

    Citation Envoyé par Obofix le gaulois Voir le message
    Dans ma tête calloc «affectait de la mémoire au pointeur mais sans le modifier». Ce qui n’a probablement aucun sens.
    Idem. calloc n'affecte rien à personne. C'est comme si, dans le code suivant...
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    int carre(int n) {
        return n*n;
    }
     
    int main()
    {
        int x=carre(5);
    }
    ...tu disais "carre affecte une valeur à x" ; ce qui est totalement faux.

    calloc alloue de la mémoire, la remplit de zéros et renvoie l'adresse de la zone allouée. Charge à celui qui l'utilise (donc toi) de récupérer cette adresse pour la stocker dans un pointeur. C'est donc toi qui affecte la mémoire au pointeur, pas calloc...

    Citation Envoyé par Obofix le gaulois Voir le message
    Les choses sont plus claires maintenant.
    Sûr ???
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

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

Discussions similaires

  1. Erreur sur une requête en utilisant la fonction somme
    Par TheFantasyRide dans le forum Requêtes et SQL.
    Réponses: 3
    Dernier message: 21/04/2009, 18h55
  2. Réponses: 10
    Dernier message: 07/08/2008, 09h09
  3. Réponses: 3
    Dernier message: 27/05/2008, 23h07
  4. [PHPMailer] Erreur lors de l'utilisation de la fonction mail
    Par onlytime dans le forum Bibliothèques et frameworks
    Réponses: 1
    Dernier message: 04/04/2008, 16h11
  5. Réponses: 2
    Dernier message: 20/04/2007, 11h52

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