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

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2008
    Messages
    89
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2008
    Messages : 89
    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 éprouvé
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    1 299
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 1 299
    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 confirmé
    Profil pro
    Inscrit en
    Avril 2008
    Messages
    89
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2008
    Messages : 89
    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 : 49

    Informations professionnelles :
    Activité : Consultant informatique

    Informations forums :
    Inscription : Juin 2009
    Messages : 1 909
    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.

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

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

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

    Informations forums :
    Inscription : Décembre 2004
    Messages : 1 299
    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 : 49

    Informations professionnelles :
    Activité : Consultant informatique

    Informations forums :
    Inscription : Juin 2009
    Messages : 1 909
    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);

  8. #8
    Membre Expert
    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
    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 : 49

    Informations professionnelles :
    Activité : Consultant informatique

    Informations forums :
    Inscription : Juin 2009
    Messages : 1 909
    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

  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
    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().

+ 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