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 :

Allocation dynamique - pointeur de pointeur de structure


Sujet :

C

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Avril 2008
    Messages
    89
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2008
    Messages : 89
    Points : 56
    Points
    56
    Par défaut Allocation dynamique - pointeur de pointeur de structure
    Bonjour,

    J'ai un petit problème pour alloué de la mémoire à un pointeur vers une structure, à l'aide de malloc().
    Le programme compile, mais plante à l'execution. En mode debug, j'ai un message d'erreur : "segmentation fault". Je pense que cela vient d'une erreur lors de l'allocation.

    Voilà mon 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
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    //La structure utilisée
    struct DATA
    {
        char *data1;
        char *data2;
    };
    typedef struct DATA data_t;
    
    //Le programme
    int main()
    {
            data_t** data;
    	int nbLignes = 2;
    	int nbCol= 4;
    	int i=0,j=0;
    	data = (data_t**)malloc(nbLignes*sizeof(data_t*));
    	*data = (data_t*)malloc(nbCol*sizeof(data_t));
    
    	for(i=0;i<nbLignes;i++){
    		for(j=0;j<nbCol; j++){
    		    printf("\ni:%d j:%d",i,j);
    			data[i][j].data1 = malloc(10*sizeof(char));  //Plantage sur cette ligne (pour i=1)
    			data[i][j].data2 = malloc(10*sizeof(char));
    		}
    	}
    
    	//Remplissage des données puis affichage
           //.........
    
          //Libération mémoire
    	for(i=0;i<nbLignes;i++){
    		for(j=0;j<nbCol; j++){
    			free(data[i][j].data1);
    			free(data[i][j].data2);
    		}
    	}
    	free(*data);
            free(data);
        return 0;
    }
    Pouvez vous m'expliquer ce qui ne va pas dans ce code ?
    Merci d'avance.

  2. #2
    Membre éclairé
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    1 298
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 1 298
    Points : 886
    Points
    886
    Par défaut
    Salut

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    data_t** data;
    data = malloc(nbLignes * sizeof(*data));
    for(i = 0 ; i < nbLignes ; i++)
      data[i] = malloc(nbColonnes * sizeof(*data[i]))
    je te laisse vérifier les erreurs de malloc (pointeur == NULL)

  3. #3
    Membre du Club
    Profil pro
    Inscrit en
    Avril 2008
    Messages
    89
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2008
    Messages : 89
    Points : 56
    Points
    56
    Par défaut
    Merci, ça marche comme ça.
    Je pensais qu'on pouvait éviter de passer par une boucle, en allouant directement sur le premier pointeur, mais apparement, ça coince.

    Pour libérer la mémoire, je dois faire pareil ou free(*data) suffit? (je n'ai pas d'erreur, mais je ne sais pas si c'est vraiment libéré ou non....)

    C'est vrai que j'ai oublié la vérification du malloc, je vais rajouter ça.

  4. #4
    Membre expert Avatar de jabbounet
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Juin 2009
    Messages
    1 909
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48

    Informations professionnelles :
    Activité : Consultant informatique

    Informations forums :
    Inscription : Juin 2009
    Messages : 1 909
    Points : 3 284
    Points
    3 284
    Par défaut
    Pour libérer la mémoire, je dois faire pareil ou free(*data) suffit? (je n'ai pas d'erreur, mais je ne sais pas si c'est vraiment libéré ou non....)
    Il faut faire pareil qu'avec malloc mais dans le sens inverse. c'est à dire d'abord desalouer ce qui a été alloué dans la boucle.
    et ensuite desalouer le premier pointeur.
    bazar: http://www.improetcompagnie.com/publ...ctacles-6.html

    BÉPO la disposition de clavier francophone, ergonomique et libre: http://bepo.fr/wiki/Accueil

    Emacs Wiki: http://www.emacswiki.org/

    En attente de ce que produira: http://www.pushmid.com

  5. #5
    Membre du Club
    Profil pro
    Inscrit en
    Avril 2008
    Messages
    89
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2008
    Messages : 89
    Points : 56
    Points
    56
    Par défaut
    C'est ce que je pensais.
    Merci pour ces précisions.

  6. #6
    Membre éclairé
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    1 298
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 1 298
    Points : 886
    Points
    886
    Par défaut
    de manière générale, tu dois avoir autant de free() que de *alloc() (calloc, malloc ou realloc)

  7. #7
    Membre expert Avatar de jabbounet
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Juin 2009
    Messages
    1 909
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48

    Informations professionnelles :
    Activité : Consultant informatique

    Informations forums :
    Inscription : Juin 2009
    Messages : 1 909
    Points : 3 284
    Points
    3 284
    Par défaut
    Citation Envoyé par salseropom Voir le message
    de manière générale, tu dois avoir autant de free() que de *alloc() (calloc, malloc ou realloc)
    Pas pour tous les cas de realloc:
    Exemple 2 alloc avec un seul free qui est correct:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    char * c = malloc(100);
    c = realloc(c,200);
    free(c);
    Si tu utilise realloc comme un malloc alors oui dans ce cas tu en as autant
    exemple:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    char *c = NULL;
    c = realloc(c,100);
    bazar: http://www.improetcompagnie.com/publ...ctacles-6.html

    BÉPO la disposition de clavier francophone, ergonomique et libre: http://bepo.fr/wiki/Accueil

    Emacs Wiki: http://www.emacswiki.org/

    En attente de ce que produira: http://www.pushmid.com

  8. #8
    Membre chevronné
    Profil pro
    Inscrit en
    Août 2006
    Messages
    1 104
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 1 104
    Points : 1 750
    Points
    1 750
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    char * c = malloc(100);
    c = realloc(c,200);
    free(c);
    Si realloc échoue, tu as une fuite de mémoire.

  9. #9
    Membre expert Avatar de jabbounet
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Juin 2009
    Messages
    1 909
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48

    Informations professionnelles :
    Activité : Consultant informatique

    Informations forums :
    Inscription : Juin 2009
    Messages : 1 909
    Points : 3 284
    Points
    3 284
    Par défaut
    Citation Envoyé par jeroman Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    char * c = malloc(100);
    c = realloc(c,200);
    free(c);
    Si realloc échoue, tu as une fuite de mémoire.
    Exact, mais le but ici n'était pas de sortir un code à toute épreuve, mais dire plutôt qu'il n'y pas toujours autant d'appel a free que d'appel aux fonctions d'allocation.

    pour info le code sans risque serait:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    char *c = malloc(100);
    char *tmp = realloc(c,200);
     
    if (tmp != NULL) {
       // la re-allocation à réussi.
       c = tmp;
    }
     
    free(c);
    Second cas particulier avec realloc:
    void *realloc(void *ptr, size_t size);
    si l'argument size vaut 0 alors l'appel deviens équivalent à un free.
    bazar: http://www.improetcompagnie.com/publ...ctacles-6.html

    BÉPO la disposition de clavier francophone, ergonomique et libre: http://bepo.fr/wiki/Accueil

    Emacs Wiki: http://www.emacswiki.org/

    En attente de ce que produira: http://www.pushmid.com

  10. #10
    Expert éminent sénior
    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
    Points : 13 926
    Points
    13 926
    Par défaut
    @jabbounet
    Second cas particulier avec realloc:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    void *realloc(void *ptr, size_t size);
    si l'argument size vaut 0 alors l'appel deviens équivalent à un free.
    La norme dit que le comportement est dépendant de l'implémentation, pas que c'est équivalent à un free().
    Publication : Concepts en C

    Mon avatar : Glenn Gould

    --------------------------------------------------------------------------
    Une réponse vous a été utile ? Remerciez son auteur en cliquant le pouce vert !

  11. #11
    Membre expert Avatar de jabbounet
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Juin 2009
    Messages
    1 909
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48

    Informations professionnelles :
    Activité : Consultant informatique

    Informations forums :
    Inscription : Juin 2009
    Messages : 1 909
    Points : 3 284
    Points
    3 284
    Par défaut
    Il va falloir mettre à jour les pages de man du site alors

    DESCRIPTION
    calloc() alloue la mémoire nécessaire pour un tableau de nmemb éléments, chacun d'eux représentant size octets, et renvoie un pointeur vers la mémoire allouée. Cette zone est remplie avec des zéros.

    malloc() alloue size octets, et renvoie un pointeur sur la mémoire allouée. Le contenu de la zone de mémoire n'est pas initialisé.

    free() libère l'espace mémoire pointé par ptr, qui a été obtenu lors d'un appel antérieur à malloc(), calloc() ou realloc(). Si le pointeur ptr n'a pas été obtenu par l'un de ces appels, ou si il a déjà été libéré avec free(), le comportement est indéterminé. Si ptr est NULL, aucune tentative de libération n'a lieu.

    realloc() modifie la taille du bloc de mémoire pointé par ptr pour l'amener à une taille de size octets. realloc() conserve le contenu de la zone mémoire minimum entre la nouvelle et l'ancienne taille. Le contenu de la zone de mémoire nouvellement allouée n'est pas initialisé. Si ptr est NULL, l'appel de realloc() est équivalent à malloc(size). Si size vaut zéro, l'appel est équivalent à free(ptr). Si ptr n'est pas NULL, il doit avoir été obtenu par un appel antérieur à malloc(), calloc() ou realloc().
    http://man.developpez.com/man3/free.3.php
    bazar: http://www.improetcompagnie.com/publ...ctacles-6.html

    BÉPO la disposition de clavier francophone, ergonomique et libre: http://bepo.fr/wiki/Accueil

    Emacs Wiki: http://www.emacswiki.org/

    En attente de ce que produira: http://www.pushmid.com

  12. #12
    Expert éminent sénior
    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
    Points : 13 926
    Points
    13 926
    Par défaut
    Il y a aussi, dans ce même texte, un peu plus loin, sur ce sujet :
    Si size vaut zéro, realloc renvoie NULL ou un pointeur acceptable pour free().
    La norme dit :
    7.20.3
    ....
    If the size of the space requested is zero, the behavior is implementation defined: either a null pointer is returned, or the behavior is as if the size were some nonzero value, except that the returned pointer shall not be used to access an object.
    Elle ne dit pas que le realloc() sera équivalent à un free() ni d'ailleurs que le pointeur retourné (si ce n'est pas NULL) est acceptable par free().
    Publication : Concepts en C

    Mon avatar : Glenn Gould

    --------------------------------------------------------------------------
    Une réponse vous a été utile ? Remerciez son auteur en cliquant le pouce vert !

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

Discussions similaires

  1. allocation dynamique avec double pointeur ou non
    Par Blackbull dans le forum C
    Réponses: 6
    Dernier message: 09/12/2012, 00h53
  2. Réponses: 3
    Dernier message: 20/09/2009, 17h40
  3. Allocation dynamique d'un tableau de structures
    Par ryadh.naouar dans le forum C
    Réponses: 5
    Dernier message: 24/04/2008, 12h49
  4. Allocation dynamique: Tableau de pointeur sur char
    Par Anonymouse dans le forum Débuter
    Réponses: 4
    Dernier message: 21/10/2007, 10h57
  5. Réponses: 6
    Dernier message: 02/11/2006, 16h44

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