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 de mémoire en langage C [Tutoriel]


Sujet :

C

  1. #1
    Expert éminent
    Avatar de PRomu@ld
    Homme Profil pro
    Ingénieur de Recherche
    Inscrit en
    Avril 2005
    Messages
    4 155
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Vienne (Poitou Charente)

    Informations professionnelles :
    Activité : Ingénieur de Recherche
    Secteur : Enseignement

    Informations forums :
    Inscription : Avril 2005
    Messages : 4 155
    Points : 6 486
    Points
    6 486
    Par défaut Allocation dynamique de mémoire en langage C
    Bonjour,

    Vous pouvez postez ici vos avis, remarques, suggestions sur l'article suivant :

    http://rperrot.developpez.com/articles/c/allocationC/

    NB: Merci de lire ce message avant de poster.

  2. #2
    Membre à l'essai
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Mars 2011
    Messages
    16
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France

    Informations professionnelles :
    Activité : Chercheur en informatique

    Informations forums :
    Inscription : Mars 2011
    Messages : 16
    Points : 20
    Points
    20
    Par défaut
    Bonsoir,

    Juste pour vous signaler une petite erreur dans un code de votre tutoriel :

    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
    int * tabentier;
    /* Création d'un tableau de 3 entiers */
    tabentier = calloc ( 3 , sizeof(int) );
     
    tabentier[0] = 1;
    tabentier[1] = 2;
    tabentier[2] = 3;
     
    /* Ajout d'un element au tableau */
    tabentier = realloc (tabentier, 4 * sizeof(int) );
     
    tabentier[3] = 4;
     
    for ( i = 0 ; i < 3 ; i++ )
    {
         printf(" tabentier[%d] = %d \n", i , tabentier[i] );
    }
    La condition de la boucle for est mauvaise : elle s’arrêtera au troisième élément du tableau, et n'affichera donc pas tabentier[3] = 4, comme attendu.

    Merci.
    Bonne continuation,
    neow_

  3. #3
    Nouveau Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2011
    Messages
    1
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Maroc

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2011
    Messages : 1
    Points : 1
    Points
    1
    Par défaut
    Citation Envoyé par neow_ Voir le message
    Bonsoir,

    la solution :

    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
    int * tabentier;
    /* Création d'un tableau de 3 entiers */
    tabentier = calloc ( 3 , sizeof(int) );
     
    tabentier[0] = 1;
    tabentier[1] = 2;
    tabentier[2] = 3;
     
    /* Ajout d'un element au tableau */
    tabentier = realloc (tabentier, 4 * sizeof(int) );
     
    tabentier[3] = 4;
     
    for ( i = 0 ; i < 4 ; i++ )
    {
         printf(" tabentier[%d] = %d \n", i , tabentier[i] );
    }
    maintenant la boucle s'amarche bien !

    Bonne chance,
    neow_

  4. #4
    Expert éminent
    Avatar de Melem
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2006
    Messages
    3 656
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Janvier 2006
    Messages : 3 656
    Points : 8 389
    Points
    8 389
    Par défaut
    Je trouve le tutoriel excellent. Cependant, il y a un problème avec les macros MALLOC, CALLOC et REALLOC. Prenons ce code tiré du tutoriel par exemple :
    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
    int ** matrice , i;         /* un tableau à deux dimension */
     
    /*allocation d'un tableau de trois tableaux d'entiers */
    MALLOC(matrice,int*,3);    
     
    for ( i = 0 ; i < 3 ; i ++ )
    {
         /* allocation d'un tableau de tableau */
         CALLOC(matrice[i],int,3); 
    }
     
    /*remplissage d'une matrice diagonale*/
    for ( i = 0 ; i < 3 ; i++ )
    {
          matrice[i][i] = 1;
    }
     
    for(i = 0 ; i<3 ; i++)
    {
         FREE(matrice[i]);
    }
    FREE(matrice);
    Si CALLOC echoue disons alors qu'on en est à i = 2, matrice[2] va certes être libéré mais le programme se termine tout de suite : matrice[1], matrice[0] et matrice n'ont pas été libérés ! Il faut donc soit les retirer du tutoriel, soit les corriger.

  5. #5
    Membre à l'essai
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Mars 2011
    Messages
    16
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France

    Informations professionnelles :
    Activité : Chercheur en informatique

    Informations forums :
    Inscription : Mars 2011
    Messages : 16
    Points : 20
    Points
    20
    Par défaut
    minfo21 > Merci, mais j'avais déjà résolu le problème, c'était juste pour signaler l'erreur.

  6. #6
    Expert confirmé
    Avatar de Thierry Chappuis
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Mai 2005
    Messages
    3 499
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : Suisse

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Industrie Pharmaceutique

    Informations forums :
    Inscription : Mai 2005
    Messages : 3 499
    Points : 5 360
    Points
    5 360
    Par défaut
    Je trouve ce didacticiel de très bonne qualité. Je reste toutefois sur ma fin par rapport aux macros proposées dans la section 4.2 qui cachent des exit() sauvages qui ne me plaisent pas. L'utilisation de tels points de sortie est certes souvent utilisé dans un contexte d'enseignement. Il y a toutefois certainement de meilleures façons de traiter ce type d'erreurs d'allocation dynamiques de mémoire dans la vraie vie. C'est à priori à mon avis une mauvaise pratique et je me demande s'il est opportun en tout cas de cacher ces points de sortie dans une macro. Typiquement, dans une fonction de création de matrice, ma stratégie sera, en cas d'erreur d'allocation, de faire le ménage (i.e. libérer tout ce qui a été allouer), puis de faire remonter l'erreur d'allocation, éventuellement jusqu'à main() qui sera la seule fonction autorisée à quitter l'application.

    Avec mes meilleures salutations

    Thierry
    "The most important thing in the kitchen is the waste paper basket and it needs to be centrally located.", Donald Knuth
    "If the only tool you have is a hammer, every problem looks like a nail.", probably Abraham Maslow

    FAQ-Python FAQ-C FAQ-C++

    +

  7. #7
    Candidat au Club
    Profil pro
    Inscrit en
    Juillet 2012
    Messages
    3
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2012
    Messages : 3
    Points : 4
    Points
    4
    Par défaut
    Bonjour,
    Ce tutoriel est très bien fait, car il ma permis de comprendre comment allouer dynamiquement un tableau à deux dimensions, par contre il y a quelque chose que je ne comprend pas. J'ai repris le code du chapitre 1.2 en le modifiant pour l'adapter à ma situation. Il marche très bien mais je comprend pas pourquoi il ne fait pas un segment fault avec ce 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
     
    //création d'un tableau de 4 tableau de 3 int
      int **tab , i;
     
      tab = (int**) malloc( 4 * sizeof(int));
     
        if( tab == NULL )
        {
            fprintf(stderr,"Allocation impossible");
            exit(EXIT_FAILURE);
        }
     
        for( i = 0 ; i < 4 ; i++ )
        {
            tab[i] = (int*) calloc (3 * sizeof(int*));
     
            if( tab[i] == NULL )
            {
                fprintf(stderr,"Allocation impossible");
                exit(EXIT_FAILURE);
            }
        }
      //Ce code marche, mais quand j’essaie d'utiliser par exemple tab[2][100] il n'y a pas de segment fault, alors que le tableau est sensé s’arrêter à tab[3][2], enfin je pense
      //*
      int x;
      int y;
      for(y = 0 ; y < 100000 ; y++)
        {
          for(x = 0 ; x < 4 ; x++)
          {
               printf("x = %d et y = %d\n", x, y);
               tab[x][y] = 0;
          }
        }//*/
    Ici, l'erreur segment fault arrive pour y = 33756 d'après la sortie du programme :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    x = 2 et y = 33755
    x = 3 et y = 33755
    x = 0 et y = 33756
    x = 1 et y = 33756
    x = 2 et y = 33756
    x = 3 et y = 33756
    Erreur de segmentation
    Je me demande si c'est normal et si oui pourquoi, pouvez vous m'expliquez s'il vous plaît ?

  8. #8
    Nouveau membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2012
    Messages
    25
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2012
    Messages : 25
    Points : 27
    Points
    27
    Par défaut
    Bonjour,


    Maintenant que nous avons expliqué comment fonctionnait la fonction realloc(), supposons que tout ne se déroule pas correctement. Par exemple il est impossible de réallouer le tableau. La fonction réalloc va donc nous renvoyer le pointeur NULL. Comme nous avons fait une affection de notre ancien tableau alors nous perdons tous ce qui y était (il s'agit en fait d'une fuite mémoire : le contenu de notre ancien tableau existerai toujours physiquement mais il serait impossible d'y accéder). Il faut donc remplacer notre fonction de réallocation par celle ci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    int * temp;
    temp = realloc (tabentier, 4 * sizeof(int) );
     
    if ( temp == NULL )
    {
         fprintf(stderr,"Reallocation impossible");
         free(tabentier);
         exit(EXIT_FAILURE);
    }
    else
    {
         tabentier = temp;
    }
    Faire la remarque me paraît très intéressant. Mais le code par contre est quelque peu lourd car on fait faire à notre programme des copies de mémoire (inutilement), copies dues notamment à l'introduction de la variable temp. On pourrait faire comme suit non ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    if(  realloc(tabentier, 4*sizeof(int))== NULL )
    {
         fprintf(stderr,"Reallocation impossible") ;
         free(tabentier) ;
         exit(EXIT_FAILURE);
    }
    else
    {
         // la mémoire nécessaire a bien été réallouée (pour tabentier)
    }
    Voilà donc ce cours exemple, qui alloue dynamiquement un entier, lui affecte la valeur 3, l'affiche et enfin le libère.
    Cette formulation est quelque peu incohérente. J'aurais préféré Voilà donc ce court exemple où nous allouons dynamiquement de la mémoire pour un entier, lui affectons la valeur 3, l'affichons et enfin libérons la mémoire demandée. Mais ce n'est qu'un point de vue après tout.

    Par ailleurs, comme l'ont dit les amis, l'utilisation des macros que tu proposes, à mon avis, n'est pas très utile : le programmeur ne doit pas trouver ennuyeux de recopier/coller les mêmes procédures de test. Mais là aussi, il ne s'agit que de mon point de vue.

    Ma conclusion : J'aime bien ton article. On voit que c'est le fruit d'un travail sérieux et pertinant. Bonne journée à vous !

  9. #9
    Membre émérite
    Avatar de imperio
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2010
    Messages
    852
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2010
    Messages : 852
    Points : 2 298
    Points
    2 298
    Par défaut
    Les fonctions qui seront décrites dans cet article appartiennent toutes au fichier d'en-tête suivant :stdlib.h .Il
    Des espaces mal places.

    Petites fautes de frappe ici :

    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
    /* le type complexe */
    struct complexe
    {
         double Re;
         double Im;
    };
    /* une défition plus courte pour la structure */
    typedef struct complexe Complexe;
    
    Complexe * c;
    
    c = malloc(sizeof(Complexe));
    
    if ( c == NULL )
    {
         fprintf(stderr,"Allocation Impossible");
         exit(EXIT_FAILURE);
    }
    Maintenant, passons à un exemple un peu plus évolué, supposons que nous voulions allouer un tableau de 3 nombres complexes.
    Apres ", passons à un exemple un peu plus évolué", je pense qu'il aurait mieux valu un point et non une virgule, ca rendrait la lecture plus agreable.

    Nous allons voir comment avec la fonction malloc nous pouvons résoudre ce problème.
    Je trouve ca horrible a lire. Comme ca ce serait pas mieux :

    Nous allons voir comment résoudre ce problème avec la fonction malloc.

    C'est donc un pointeur vers le premier élément du tableau qui est renvoyé.Ceci est donc conforme avec le fait qu'un tableau est égal (en terme de pointeur) au premier élément du tableau. (ie : tab == tab[0] )
    Il manque un espace a la fin de la premiere phrase.

    Pour accéder à la deuxième case du tableau, il suffit d'ajouter la taille d'un bloc à l'adresse du premier élément(obtenue avec sizeof).
    Il manque encore un espace.

    On peut également utiliser une autre méthode, utiliser l'arithmétique des pointeurs.
    Comme ca ce serait pas mieux ?

    On peut également utiliser une autre méthode : l'arithmétique des pointeurs.

    Ce qui facilite grandement le travail du programmeur, et permet de ne pas faire de différence à l'utilisation entre tableaux dynamiques et tableaux statiques.
    Je pensais qu'on disait developpeur et non programmeur mais la je suis pas sur de mon coup.

    Revenons un peu sur l'allocation de notre tableau, comme nous l'avons vu précédemment,
    J'aurais mis un point juste apres tableau. Comme ceci :

    Revenons un peu sur l'allocation de notre tableau. Comme nous l'avons vu précédemment,
    La fonction alloue n blocs de taille t. elle est donc presque équivalente à l'appel suivant :
    Une majuscule a ete oubliee.

    La seule différence réside dans le contenu des cases qui sont allouée.
    Il manque un 's' a allouee.

    Si ce n'est ce point de détail
    Bizarre cette phrase, nan ?

    Voici donc comment on alloue un tableau de trois tableau de trois entier.
    Il manque un 's' a entier.

    On utilise la fonction malloc() ici mais on pourrai utiliser calloc(), c'est juste pour vous montrer que l'on peut utiliser les deux.
    Il manque un 't' a pourrai.

    Passons maintenant à la dernière fonction d'allocation : la fonction realloc() voici sa signature :
    Il manque de la ponctuation la.

    Juste après intervient la fonction realloc(), celle ci réalloue le bloc mémoire contenant notre tableau en changeant sa taille.
    J'aurais mis un point juste avant "celle ci realloue". Et j'aurais ecrit "celle-ci" et non pas "celle ci". Mais comme ca revient souvent ca doit pas etre genant.

    Cet exemple montre bien que la fonction réalloc recopie notre tableau, et modifie sa taille .
    Il y a une virgule en trop.

    le contenu de notre ancien tableau existerai toujours physiquement mais il serait impossible d'y accéder)
    Il manque un 't' a existerai.

    Je me suis arrete la mais je pense qu'une relecture serait necessaire.

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

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 518
    Points
    41 518
    Par défaut
    @hantoine: Tu alloues un tableau de 4*3, tab[2][100] n'existe donc pas et tenter d'y accéder est un comportement indéfini.

    Citation Envoyé par leMédaillon Voir le message
    Bonjour,

    Faire la remarque me paraît très intéressant. Mais le code par contre est quelque peu lourd car on fait faire à notre programme des copies de mémoire (inutilement), copies dues notamment à l'introduction de la variable temp. On pourrait faire comme suit non ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    if(  realloc(tabentier, 4*sizeof(int))== NULL )
    {
         fprintf(stderr,"Reallocation impossible") ;
         free(tabentier) ;
         exit(EXIT_FAILURE);
    }
    else
    {
         // la mémoire nécessaire a bien été réallouée (pour tabentier)
    }
    Non, car realloc() peut retourner une valeur qui n'est ni tabentier, ni NULL.
    Si tu veux une version "plus simple", regarde plutôt prendre le pointeur par adresse.
    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.

  11. #11
    Nouveau membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2012
    Messages
    25
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2012
    Messages : 25
    Points : 27
    Points
    27
    Par défaut
    Citation Envoyé par Médinoc Voir le message

    Non, car realloc() peut retourner une valeur qui n'est ni tabentier, ni NULL.
    Si tu veux une version "plus simple", regarde plutôt prendre le pointeur par adresse.
    Oui en effet : je viens de relire le manuel et j'ai pu y lire

    par le manuel : [...] realloc() renvoie un pointeur sur la mémoire nouvellement allouée, qui est correctement alignée pour n’importe quel type de variable, et qui peut être différent de ptr, ou NULL si la demande échoue. [...]
    On part donc de l'ypothèse que tu as raison et nous considérons donc le code suivant :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    int * temp;
    temp = realloc (tabentier, 4 * sizeof(int) );
     
    if ( temp == NULL )
    {
         fprintf(stderr,"Reallocation impossible");
         free(tabentier);
         exit(EXIT_FAILURE);
    }
    else
    {
         tabentier = temp;
    }
    Imagines que realloc retourne une valeur différente de NULL et de tabentier. Quel intérêt ont donc les instructions du else (dans le code précité) ? Je veux parler surtout de l'instruction tabentier = temp; (vu que temp ne vaut ni NULL, ni tabentier).

  12. #12
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Juin 2009
    Messages
    4 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 481
    Points : 13 679
    Points
    13 679
    Billets dans le blog
    1
    Par défaut
    S'il ne vaut ni NULL ni tabentier, alors c'est la nouvelle adresse et il faut peut-être la sauvegarder ?

    De plus, la "lenteur" induite par la copie d'une variable temporaire est probablement complètement négligeable devant une réallocation.

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

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 518
    Points
    41 518
    Par défaut
    Si realloc() ne retourne ni NULL ni tabentier, ça veut dire:
    1. Le pointeur retourné pointe sur le buffer voulu,
    2. tabentier n'est plus un pointeur valide (realloc() a fait un free() dessus).

    En gros, realloc() a du retourner un nouveau tableau car il n'a pas pu l'agrandir sur place (probablement parce qu'il y avait quelque chose d'alloué derrière).

    Il faut donc utiliser la nouvelle valeur.


    En fait, dans le cas où realloc() marcherait systématiquement, on pourrait faire systématiquement tabentier = realloc(tabentier, nouvelle_taille);. Mais quand realloc() échoue, cette ligne devient mauvaise car le tableau n'a pas été désalloué!
    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.

  14. #14
    Nouveau membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2012
    Messages
    25
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2012
    Messages : 25
    Points : 27
    Points
    27
    Par défaut
    Citation Envoyé par Bktero Voir le message
    S'il ne vaut ni NULL ni tabentier, alors c'est la nouvelle adresse et il faut peut-être la sauvegarder ? [...]
    Humm je suis quelque peu confus là. Je voudrais donc savoir. Dans le texte suivant (tiré du manuel)

    par le manuel : [...] realloc() renvoie un pointeur sur la mémoire nouvellement allouée, qui est correctement alignée pour n’importe quel type de variable, et qui peut être différent de ptr, ou NULL si la demande échoue. [...]
    de quel ptr parle-t-il ? Est-ce ptr avant reallocation ? Ou est-ce ptr après reallocation ? Il faut surtout noter que je reste toujours inconvaincu. Mais je veux bien vous rassurer que mon but n'est pas de vous importuner, chers internautes. La réponse de medinoc, bien qu'intéressante, ne me fait pas me rendre compte de la différence entre les deux codes suivants

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    int * temp;
    temp = realloc (tabentier, 4 * sizeof(int) );
     
    if ( temp == NULL )
    {
         fprintf(stderr,"Reallocation impossible");
         free(tabentier);
         exit(EXIT_FAILURE);
    }
    else
    {
         tabentier = temp;
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    if(  realloc(tabentier, 4*sizeof(int))== NULL )
    {
         fprintf(stderr,"Reallocation impossible") ;
         free(tabentier) ;
         exit(EXIT_FAILURE);
    }
    else
    {
         // la mémoire nécessaire a bien été réallouée (pour tabentier)
    }
    Y-aurait-il une autre explication ? Ou c'est juste une façon de faire utilisée par les développeurs professionnels, façon de faire que je devrais peut-être suivre ?

  15. #15
    Nouveau membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2012
    Messages
    25
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2012
    Messages : 25
    Points : 27
    Points
    27
    Par défaut
    Par medinoc

    Si realloc() ne retourne ni NULL ni tabentier, ça veut dire:
    1. Le pointeur retourné pointe sur le buffer voulu,
    2. tabentier n'est plus un pointeur valide (realloc() a fait un free() dessus).
    Je comprends beaucoup mieux. J'en conclue donc que PRomu@ld avait fait le bon choix et je rectifierais en conséquence cette erreur que je fais souvent dans mes codes avec realloc. Bonne soirée à vous !

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

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 518
    Points
    41 518
    Par défaut
    Citation Envoyé par leMédaillon Voir le message
    de quel ptr parle-t-il ? Est-ce ptr avant reallocation ? Ou est-ce ptr après reallocation ?
    C'est forcément ptr avant réallocation, parce que realloc() ne peut pas modifier ptr.

    Si realloc() pouvait modifier ptr, on aurait juste besoin de savoir si elle a réussi ou échoué. C'est ce que fait la version au bout de ce lien.
    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.

  17. #17
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Juin 2009
    Messages
    4 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 481
    Points : 13 679
    Points
    13 679
    Billets dans le blog
    1
    Par défaut
    Ce code
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    if(  realloc(tabentier, 4*sizeof(int))== NULL )
    {
         fprintf(stderr,"Reallocation impossible") ;
         free(tabentier) ;
         exit(EXIT_FAILURE);
    }
    else
    {
         // la mémoire nécessaire a bien été réallouée (pour tabentier)
    }
    ne peut pas fonctionner car comme le fait très justement remarqué Médinoc
    realloc() ne peut pas modifier ptr
    En effet, il aurait fallu que realloc() prenne en paramètre un pointeur sur pointeur pour pouvoir modifier tabentier. Par conséquent, tu passes une adresse à realloc() via ce pointeur et il te renvoie une nouvelle adresse que tu stockes dans la variable que tu veux (le plus logique étant dans tabentier mais ce n'est pas obligatoire).

    PS : je ne sais pas si ça a été dit clairement mais il est bien sûr possible que le retour de realloc() soit égal à tabentier. Cela arrive s'il y avait de la place "à suivre" dans la mémoire.

  18. #18
    Candidat au Club
    Profil pro
    Inscrit en
    Juillet 2012
    Messages
    3
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2012
    Messages : 3
    Points : 4
    Points
    4
    Par défaut
    Citation Envoyé par Médinoc Voir le message
    @hantoine: Tu alloues un tableau de 4*3, tab[2][100] n'existe donc pas et tenter d'y accéder est un comportement indéfini.
    Tout d'abord merci de m'avoir répondu.
    Justement ce que je ne comprend pas c'est que quand le programme tente d'accéder à tab[2][100], il y arrive, et parviens même à modifier la valeur de tab[2][100] sans que le programme ne s’arrête avec un message : erreur de segmentation. Peux tu préciser ce que tu veux dire par "un comportement indéfini".

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

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 518
    Points
    41 518
    Par défaut
    Ça veut dire qu'absolument n'importe quoi peut arriver, y compris, selon la légende, faire sortir des démons de ton nez.

    Ça peut planter tout de suite car tu tapes sur une page mémoire (typiquement par tranches de 4ko ou 8ko) non-allouée, ça peut planter plus tard parce que tu as corrompu un truc, ça peut ne jamais planter, ça peut "planter plus tard" après ta prochaine modif de code dans 20 ans, ça peut planter sur la prochaine version de Windows, etc.
    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.

  20. #20
    Candidat au Club
    Profil pro
    Inscrit en
    Juillet 2012
    Messages
    3
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2012
    Messages : 3
    Points : 4
    Points
    4
    Par défaut
    Ah ok je comprend, merci beaucoup pour tes explications.

Discussions similaires

  1. probleme d'allocation dynamique de mémoire
    Par Blo0d4x3 dans le forum C
    Réponses: 2
    Dernier message: 13/03/2007, 07h53
  2. Allocation dynamique de mémoire : Limitations ?
    Par rulianf dans le forum C++
    Réponses: 5
    Dernier message: 22/03/2006, 17h03
  3. Allocation dynamique de mémoire
    Par cd090580 dans le forum Autres éditeurs
    Réponses: 7
    Dernier message: 12/11/2005, 11h17
  4. [VC++/ASM] Allocation dynamique de mémoire ?
    Par Magus (Dave) dans le forum x86 32-bits / 64-bits
    Réponses: 7
    Dernier message: 21/12/2004, 15h05
  5. Allocation dynamique de mémoire en asm
    Par narmataru dans le forum Assembleur
    Réponses: 7
    Dernier message: 17/12/2002, 22h31

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