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 :

Problème de réallocation de mémoire de tableau 2d


Sujet :

C

  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    210
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Avril 2007
    Messages : 210
    Points : 91
    Points
    91
    Par défaut Problème de réallocation de mémoire de tableau 2d
    Bonjour à tous,

    J'ai un petit soucis avec un tableau. J'ai réussi à allouer la mémoire (ouf) mais je pense que mon code est foireux (... en effet, j'ai une erreur de segmentation) lors de la réalloaction:

    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
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <unistd.h>
     
    int main()
    {
     
      int i,j=0;
      char ***tableau=NULL;
      int nombre_de_ligne = 4;
      int tableau_nombre_de_colonne[4]={4, 2, 3, 5};
      //allocation
      tableau =  malloc(nombre_de_ligne * sizeof tableau);
     
    	for(i=0; i < nombre_de_ligne; i++)
      {
    		tableau[i]= malloc(tableau_nombre_de_colonne[i]*sizeof tableau[i]);
        for(j=0; j<tableau_nombre_de_colonne[i];j++)
        {
    		  tableau[i][j] = malloc(65 * sizeof *tableau[i][j]);  
        }  
      }
      //reallocation
      nombre_de_ligne = 6;
      int nouveau_tableau_nombre_de_colonne[6]={1,4, 7, 3, 2,9};
     
      tableau =  realloc(tableau,nombre_de_ligne * sizeof tableau);
      for(i =0; i < nombre_de_ligne; i++)
      {
     
        tableau[i]= realloc(tableau[i],tableau_nombre_de_colonne[i]*sizeof tableau[i]);
     
        for(j=0; j<nouveau_tableau_nombre_de_colonne[i];j++)
        {
          tableau[i][j] = realloc(tableau[i][j],65 * sizeof *tableau[i][j]);  
        }
     
      }
     
    }
    Merci de votre aide

  2. #2
    Membre averti

    Homme Profil pro
    Enseignant
    Inscrit en
    Septembre 2012
    Messages
    313
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Septembre 2012
    Messages : 313
    Points : 354
    Points
    354
    Par défaut
    Je ne suis pas certain de ce que tu voudrais faire avec ce programme...

    Quand je lis cette instruction:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    tableau[i][j] = realloc(tableau[i][j],65 * sizeof *tableau[i][j]);
    Je suis étonné que le compilateur ne bronche pas... je pensais que sizeof était une macro qui acceptait un paramètre: sizeof(variable), par exemple.
    Quand j'exécute ton programme, j'ai en effet une erreur de segmentation à un moment à cette ligne de code.

    Il faudrait vérifier si tableau[i][j] contiendrait NULL ou pas... comme realloc() utilise l'ancienne adresse pour lui fournir une "nouvelle taille" à ton tableau, si jamais l'adresse est à NULL (la reallocation n'a pas réussi) tu risques de planter ton application...

  3. #3
    Membre averti

    Homme Profil pro
    Enseignant
    Inscrit en
    Septembre 2012
    Messages
    313
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Septembre 2012
    Messages : 313
    Points : 354
    Points
    354
    Par défaut
    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
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <unistd.h>
     
    int main()
    {
     
      int i,j=0;
      char ***tableau=NULL;
      int nombre_de_ligne = 4;
      int tableau_nombre_de_colonne[4]={4, 2, 3, 5};
      //allocation
      tableau =  malloc(nombre_de_ligne * sizeof(tableau));
     
    	if(tableau==NULL) 
    	{
    		fprintf(stderr,"Erreur d'allocation de mémoire (1)\n");
    		exit(1);
    	}
     
    	for(i=0; i < nombre_de_ligne; i++)
      {
    		tableau[i]= malloc(tableau_nombre_de_colonne[i]*sizeof(tableau[i]));
    		if(tableau[i]==NULL) 
    		{
    			fprintf(stderr,"Erreur d'allocation de mémoire (2)\n");
    			exit(2);
    		}
        for(j=0; j<tableau_nombre_de_colonne[i];j++)
        {
    		  tableau[i][j] = malloc(65 * sizeof (*tableau[i][j]));  
        }  
      }
      //reallocation
      nombre_de_ligne = 6;
      int nouveau_tableau_nombre_de_colonne[6]={1,4, 7, 3, 2,9};
     
    	fprintf(stderr,"DEBUG: ICI (1)\n");
     
      tableau =  realloc(tableau,nombre_de_ligne * sizeof(tableau));
    	if(tableau==NULL)
    	{
    		if(tableau==NULL) 
    		{
    			fprintf(stderr,"Erreur d'allocation de mémoire (3)\n");
    			exit(3);
    		}
    	}
      for(i =0; i < nombre_de_ligne; i++)
      {
    		fprintf(stderr,"DEBUG: ICI (2)\n");
        tableau[i]= realloc(tableau[i],tableau_nombre_de_colonne[i]*sizeof(tableau[i]));
    		if(tableau[i]==NULL) 
    		{
    			fprintf(stderr,"Erreur d'allocation de mémoire (3)\n");
    			exit(4);
    		}
        for(j=0; j<nouveau_tableau_nombre_de_colonne[i];j++)
        {
    			fprintf(stderr,"DEBUG: ICI (3)\n");
          tableau[i][j] = realloc(tableau[i][j],65 * sizeof (*tableau[i][j]));  
    			if(tableau[i][j]==NULL) 
    			{
    				fprintf(stderr,"Erreur d'allocation de mémoire (4)\n");
    				exit(4);
    			}
        }
    		fprintf(stderr,"DEBUG: ICI (4)\n");
      }
      fprintf(stderr,"DEBUG: ICI (5)\n");
    }
    Comme j'ai pas beaucoup dormi cette nuit je n'ai pas la volonté de chercher à comprendre pourquoi tu veux changer la taille de ton tableau.
    Voilà ce que j'ai été capable de faire ce matin lol !!

  4. #4
    Expert éminent
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Décembre 2015
    Messages
    1 565
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

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

    Informations forums :
    Inscription : Décembre 2015
    Messages : 1 565
    Points : 7 648
    Points
    7 648
    Par défaut
    Bonjour,

    Ça me parait être un exercice particulièrement tordu. C'est très loin d'être simple.
    Quand tu fait un realloc(), tu dois passer en paramètre un pointeur qui a été préalablement alloué. En retour tu auras une nouvelle allocation et tes données précédentes transférées dedans.
    - Si la taille réallouée est plus petite: Tu perds des données donc ici des pointeurs sur des allocations sont irrémédiablement perdus et tu as une fuite mémoire! Il faut donc utiliser free() à bon escient avant d'appeler realloc()!
    - Si la taille réallouée est plus grande: Tu as à la fin de la zone allouée des pointeurs aléatoires! Appeler realloc() sur ces pointeurs aléatoires donneras un plantage. Il faut utiliser malloc() et pas realloc() pour créer ces nouvelles allocations.

    Ecrire ce code sur un tableau 2D est complexe, mais ici tu as un tableau 3D, il faut une très bonne connaissance du langage pour ne pas s'y perdre.

    Si ta réorganisation de tableau était à nombre total d'objet constant, il faudrait re-répartir les données initiales dans le tableau final. Au moins ça, ça aurait un sens. Et pour résoudre ce problème, il serait par exemple beaucoup plus simple de ne pas utiliser realloc(). On crée un tout nouveau tableau destination avec des malloc(), on transfère toutes les données dans le nouveau tableau, on libère le tableau initial avec des free().

  5. #5
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 685
    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 685
    Points : 30 974
    Points
    30 974
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par sebaaas Voir le message
    Bonjour à tous,
    Salut

    Citation Envoyé par sebaaas Voir le message
    J'ai un petit soucis avec un tableau. J'ai réussi à allouer la mémoire (ouf) mais je pense que mon code est foireux (... en effet, j'ai une erreur de segmentation) lors de la réalloaction:
    Déjà ton titre parle de tableau 2D (typiquement un échiquier) mais tes 3 étoiles (et tes 3 allocations imbriquées) sont représentatifs d'un tableau 3D (typiquement un rubik's cube). Or bien conceptualiser ses objets est un impératif.
    Ensuite je voudrais faire un parallèle sur tes 3 allocations
    • tableau = malloc(nombre_de_ligne * sizeof tableau)
    • tableau[i]= malloc(tableau_nombre_de_colonne[i] * sizeof tableau[i])
    • tableau[i][j] = malloc(65 * sizeof *tableau[i][j])

    Est-ce que tu vois la différence entre la 3° syntaxe (correcte) et les deux précédentes (incorrectes)?

    Mis à part ce détail (qui est le caillou qui fait tout planter) ton code me semble correct. Désolé peut pas tester suis pas chez-moi en ce moment (je pourrai vendredi si c'est pas réglé d'ici là).

    Sinon tester le malloc c'est bien mais ta solution de tout quitter en vrac n'est pas bonne. Une bonne gestion c'est "un malloc rate alors je nettoie tout ce qui a été alloué et je retourne une valeur spécifique à l'appelant qui gérera ce souci de son côté". De même pour un realloc on ne réalloue jamais le pointeur alloué. D'abord on réalloue sur un pointeur temporaire ce qui permet de ne pas perdre le pointeur originel afin de pouvoir le libérer si la réallocation échoue. Et si la réallocation réussit alors là on recopie le pointeur temporaire dans le pointeur originel. Hé oui, bien gérer une allocation ce n'est pas évident. C'est pour cela qu'on essaye généralement de ne pas dépasser la 2D voire même rester en 1D et convertir ensuite les coordonnées 2D (3D) en 1D (après tout, un rubuk's cube ce ne sont que des petits cubes qu'on peut mettre sur une ligne). Ainsi un seul gros malloc au lieu de plein de petits.

    Citation Envoyé par dalfab Voir le message
    - Si la taille réallouée est plus petite: Tu perds des données donc ici des pointeurs sur des allocations sont irrémédiablement perdus
    T'es sûr? Il me semble (à prendre au conditionnel car je n'ai plus l'origine de ce souvenir) qu'un realloc plus petit ne fait rien du tout... En tout cas si c'est vrai c'est une très bonne remarque !!!

    Citation Envoyé par dalfab Voir le message
    - Si la taille réallouée est plus grande: Tu as à la fin de la zone allouée des pointeurs aléatoires! Appeler realloc() sur ces pointeurs aléatoires donneras un plantage. Il faut utiliser malloc() et pas realloc() pour créer ces nouvelles allocations.
    Là aussi très bien vu
    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 sénior
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 630
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 630
    Points : 10 556
    Points
    10 556
    Par défaut
    Citation Envoyé par dalfab Voir le message
    Quand tu fait un realloc(), tu dois passer en paramètre un pointeur qui a été préalablement alloué.
    realloc fait aussi malloc si tu lui passes NULL.
    realloc, documentation en anglais sur cplusplus.com.

    Et ensuite, je n'ai pas envie/ le temps de tester , mais tu as 1 tableau d'adresses.
    Mais comme chaque case contient 1 adresse, tu peux également allouer 1 tableau d'adresses

    Donc : void* tableau=NULL; ou 1 truc comme cela

    tableau : | A | B | ... | X |

    Avec (ici on a des tableaux d'adresses/ de tableaux) :
    A pointant vers | A1 | A2 | ... | AX |
    B pointant vers | B1 | B2 | ... | BX |
    ...
    X pointant vers | X1 | X2 | ... | XX |

    Et (ici on a des tableaux de char donc char* XX) :
    A1 pointant vers | A11 | A12 | ... | A1X |
    A2 pointant vers | A21 | A22 | ... | A2X |
    ...
    AX pointant vers | AX1 | AX2 | ... | AXX |

  7. #7
    Membre expérimenté
    Homme Profil pro
    Chef de projet NTIC
    Inscrit en
    Juillet 2020
    Messages
    352
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Chef de projet NTIC

    Informations forums :
    Inscription : Juillet 2020
    Messages : 352
    Points : 1 376
    Points
    1 376
    Par défaut
    Bonjour,
    ce qui peut également énormément simplifier le code est :
    1. créer une structure de données adaptée ;
    2. créer les primitives d'accès ;


    Là on a le choix :
    • tableau à croissance dynamique ;
    • liste, éventuellement implémentée sous forme de tableau ;
    • comme le PO cherche des listes de listes de strings on peut éventuellement se poser la question si un trie, ou toute autre structure arborescente, ne ferait pas l'affaire ;


    Mais l'important est surtout de ne pas traîner partout de tonnes de *, de créer une (ou plusieurs) structure de données adaptée et écrire des fonctions.

  8. #8
    Membre régulier
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    210
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Avril 2007
    Messages : 210
    Points : 91
    Points
    91
    Par défaut
    Bonsoir et merci pour vos réponses.

    J'ai lu avec attention vos commentaires et décider de simplifier. En effet, les données du 1er tableau ne doivent pas être repris dans le 2ème tableau. Donc j'alloue un premier tableau, je libère la mémoire et j'alloue à nouveau le tableau

    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
    45
    46
    47
    48
    49
    50
    51
    52
    53
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <time.h>
     
    int main()
    {
     
      int i,j=0;
      const int MIN = 1, MAX = 100;
      char ***tableau=NULL;
      int nombre_de_ligne = 4;
      int *tableau_nombre_de_colonne=malloc((nombre_de_ligne)*sizeof(int));
      srand(time(NULL));//pour la génération d'un nombre aléatoire
     
      //allocation
      tableau =  malloc(nombre_de_ligne * sizeof tableau);
     
    	for(i=0; i < nombre_de_ligne; i++)
      {
        //nombre de colonne aleatoire
        tableau_nombre_de_colonne[i]= (rand() % (MAX + 1 - MIN)) + MIN;//nombre de colonne aleatoire
        printf("Colonne %d \n",tableau_nombre_de_colonne[i]);
    		tableau[i]= malloc(tableau_nombre_de_colonne[i]*sizeof tableau[i]);
        for(j=0; j<tableau_nombre_de_colonne[i];j++)
        {
    		  tableau[i][j] = malloc(65 * sizeof *tableau[i][j]); 
          tableau[i][j] = "1111111111111111111111111111111111111111111111111111111111111111"; 
        }  
      }
     
      //libération mémoire
      free(tableau);
     
      //reallocation
      nombre_de_ligne = 6;
     
      tableau =  malloc(nombre_de_ligne * sizeof tableau);
     
    	for(i=0; i < nombre_de_ligne; i++)
      {
        tableau_nombre_de_colonne[i]= (rand() % (MAX + 1 - MIN)) + MIN;
        printf("Colonne nouvelle alloc %d \n",tableau_nombre_de_colonne[i]);
    		tableau[i]= malloc(tableau_nombre_de_colonne[i]*sizeof tableau[i]);
        for(j=0; j<tableau_nombre_de_colonne[i];j++)
        {
    		  tableau[i][j] = malloc(65 * sizeof *tableau[i][j]); 
          tableau[i][j] = "1111111111111111111111111111111111111111111111111111111111111111"; 
        }  
      }
     return(0);
    }
    et ... cela marche. Enfin dans mes premiers tests

  9. #9
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 685
    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 685
    Points : 30 974
    Points
    30 974
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par sebaaas Voir le message
    Donc j'alloue un premier tableau, je libère la mémoire et j'alloue à nouveau le tableau
    On peut se demander alors à quoi sert l'allocation du premier tableau.
    Ceci dit, tu as toujours un souci de syntaxe incorrecte ici tableau = malloc(nombre_de_ligne * sizeof tableau) et ici tableau[i]= malloc(tableau_nombre_de_colonne[i]*sizeof tableau[i]). Alors que ton premier malloc int *tableau_nombre_de_colonne=malloc((nombre_de_ligne)*sizeof(int)) est parfait (si on fait abstractions des parenthèses inutiles). De même le dernier malloc tableau[i][j] = malloc(65 * sizeof *tableau[i][j]) est bon lui aussi. Je te donne un indice: c'est au sizeof() que ça chie.

    Accessoirement tu as un autre souci sur ces deux lignes
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    tableau[i][j] = malloc(65 * sizeof *tableau[i][j]); 
    tableau[i][j] = "1111111111111111111111111111111111111111111111111111111111111111";
    Est-ce que tu vois l'erreur? Peut-être sera-t-elle plus parlante si je l'écris ainsi
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    int var;
    var=123;
    var=456;
    ...

    Et ta libération est bancale car tu ne fais que libérer le premier pointeur alloué.Tu penses que ça libèrera les autres en cascade? Tel tu as alloué, tel (enfin dans l'utre sens) tu dois désallouer.

    Citation Envoyé par sebaaas Voir le message
    et ... cela marche. Enfin dans mes premiers tests
    Tout comme le type qui tombe de la tour. Tant qu'il n'est pas arrivé en bas, jusqu'ici ça va. Continue tes tests jusqu'au free(tableau[i][j])...
    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]

  10. #10
    Membre régulier
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    210
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Avril 2007
    Messages : 210
    Points : 91
    Points
    91
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    On peut se demander alors à quoi sert l'allocation du premier tableau.
    Pour être un peu plus complet, j'obtiens les données d'un base de donnée. Lorsqu'il y a un changement dans la base de donnée, je refait un nouveau tableau :-) avec les nouvelles données.
    Citation Envoyé par Sve@r Voir le message
    Ceci dit, tu as toujours un souci de syntaxe incorrecte
    Ce que je veux faire, c'est allouer puis remplir. J'ai changé par
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    tableau[i][j] = malloc(65 * sizeof(char));
    et
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    strcpy(tableau[i][j], "0000000000000000000000000000000000000000000000000000000000000000\0");
    J'ai également changer la libération

    Ce qui me donne :

    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
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <time.h>
     
    int main()
    {
     
      int i,j=0;
      const int MIN = 1, MAX = 100;
      char ***tableau=NULL;
      int nombre_de_ligne = 4;
      int *tableau_nombre_de_colonne=malloc(nombre_de_ligne * sizeof(int));
      srand(time(NULL));//pour la génération d'un nombre aléatoire
     
      //allocation
      tableau =  malloc(nombre_de_ligne * sizeof (char **));
     
    	for(i=0; i < nombre_de_ligne; i++)
      {
        //nombre de colonne aleatoire
        tableau_nombre_de_colonne[i]= (rand() % (MAX + 1 - MIN)) + MIN;//nombre de colonne aleatoire
        printf("Colonne %d \n",tableau_nombre_de_colonne[i]);
    		tableau[i]= malloc(tableau_nombre_de_colonne[i] * sizeof (char*));
        for(j=0; j<tableau_nombre_de_colonne[i];j++)
        {
    		  tableau[i][j] = malloc(65 * sizeof(char));    
        }  
      }
      //attribution des valeurs
      for(i=0; i < nombre_de_ligne; i++)
      {
        for(j=0; j<tableau_nombre_de_colonne[i];j++)
        {
       strcpy(tableau[i][j], "1111111111111111111111111111111111111111111111111111111111111111\0");
        }
      }
      //libération mémoire
     
      for(i=0; i < nombre_de_ligne; i++)
      {		
        for(j=0; j<tableau_nombre_de_colonne[i];j++)
        {  
    		  free(tableau[i][j]);   
        }  
        free(tableau[i]);
      }
      free(tableau);
      //reallocation
      nombre_de_ligne = 6;
     
      tableau =  malloc(nombre_de_ligne * sizeof (char **));
     
    	for(i=0; i < nombre_de_ligne; i++)
      {
        tableau_nombre_de_colonne[i]= (rand() % (MAX + 1 - MIN)) + MIN;
        printf("Colonne nouvelle alloc %d \n",tableau_nombre_de_colonne[i]);
    		tableau[i]= malloc(tableau_nombre_de_colonne[i] * sizeof (char*));
        for(j=0; j<tableau_nombre_de_colonne[i];j++)
        {
    		 tableau[i][j] = malloc(65 * sizeof(char));    
        }  
      }
      //attribution des valeurs
      for(i=0; i < nombre_de_ligne; i++)
      {
        for(j=0; j<tableau_nombre_de_colonne[i];j++)
        {
       strcpy(tableau[i][j], "0000000000000000000000000000000000000000000000000000000000000000\0");
     
        }
      }
     return(0);
    }
    ... qui fonctionne également pour le moment

  11. #11
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 685
    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 685
    Points : 30 974
    Points
    30 974
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par sebaaas Voir le message
    Pour être un peu plus complet, j'obtiens les données d'un base de donnée. Lorsqu'il y a un changement dans la base de donnée, je refait un nouveau tableau :-) avec les nouvelles données.
    Bigre, tu claques toute ta bdd en RAM? Tu es généreux!!!

    Citation Envoyé par sebaaas Voir le message
    J'ai changé par
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    tableau[i][j] = malloc(65 * sizeof(char));
    et
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    strcpy(tableau[i][j], "0000000000000000000000000000000000000000000000000000000000000000\0");
    Mieux. Tu n'étais pas obligé de changer le malloc puisque celui-là c'était justement le seul à être correct mais cette nouvelle écriture est bonne aussi. Et évidemment tu as bien compris que si tableau[i][j] contient une certaine valeur (en l'occurrence l'adresse de la zone allouée) il t'est alors définitivement interdit de lui mettre une autre valeur (sinon tu perds l'adresse allouée => fuite mémoire). Autrement dit, écrire truc=malloc(...) t'interdit définitivement et en toute circonstances d'écrire ensuite truc=quoi que ce soit si tu n'écris pas auparavant free(truc).
    Pour le strcpy() tu n'as pas besoin de mettre "\0, la fonction s'en charge (comme toute fonction de création de string).

    Citation Envoyé par sebaaas Voir le message
    J'ai également changé la libération... qui fonctionne également pour le moment
    Ok, là c'est bon. Tu n'étais pas obligé de refaire la boucle pour remplir le tableau (tu pouvais le remplir avec l'allocation) mais si tu préfères ainsi...

    C'est toutefois dommage que tu n'aies jamais trouvé ce qui n'allait pas dans les premières allocations. Tu as opté pour une pirouette en mettant le type de l'item à allouer dans le sizeof. Ca fonctionne mais si demain ton tableau évolue (sait-on jamais) il te faut tout revérifier les lignes d'allocations.
    Pourtant tu étais pas loin. Voici un exemple de tes 4 allocations
    • char ***tableau = malloc(nombre_de_ligne * sizeof (char **))
    • char ***tableau = malloc(nombre_de_ligne * sizeof tableau)
    • char *tableau[i][j] = malloc(65 * sizeof char)
    • char *tableau[i][j] = malloc(65 * sizeof *tableau[i][j])


    Les allocations 1, 3 et 4 sont bonnes. La seconde est mauvaise. Et je t'avais dit que c'était au sizeof que ça cafouillait. Et ce n'est pas à cause du type puisque l'allocation 4 ne fait pas référence au type (enfin pas diretement). Donc ce qui cloche dans l'allocation 2, c'est "tableau". Tu ne peux pas demander "taille tableau" car tu ne connais pas la taille du tableau (c'est pas logique, il n'a pas encore été alloué). En revanche, tu connais la taille d'un élément. Et c'est quoi un élément? C'est un "char étoile étoile" ou alors un "étoile tableau"!!!
    Ben oui, "tableau" est un "char étoile étoile étoile". Donc "étoile tableau" est un "char étoile étoile", et "étoile étoile tableau" est un "char étoile" et "étoile étoile étoile tableau" est un "char".
    Allouer n "char étoile étoile" (allocation n° 1) c'est allouer n "étoile tableau" => char ***tableau = malloc(nombre_de_ligne * sizeof(*tableau)). Ensuite l'allocation intermédiaire tableau[i]=malloc(tableau_nombre_de_colonne[i]*sizeof tableau[i]) où tu devais allouer n "char étoile" devient alors tableau[i]=malloc(tableau_nombre_de_colonne[i]*sizeof(*tableau[i])). Mais le plus dommage c'est que la dernière allocation char *tableau[i][j] = malloc(65 * sizeof(*tableau[i][j])) elle était parfaite. Elle aurait dû te mettre sur la voie...
    Alors ça fonctionnait car du point de vue assembleur un "char étoile étoile" ou un "char étoile étoile étoile" c'est la même chose (une simple adresse et sizeof(adresse) ça ne change pas) mais ça restait incorrect. Et en C, un truc incorrect il te pête à la figure tôt ou tard (et plus c'est tard plus c'est difficile de trouver l'origine).

    Pour simplifier, chaque fois que tu écris truc=malloc(...), quel que soit "truc", tu mets systématiquement étoile truc dans le sizeof. Et ça marche (exemple ta 3° allocation tableau[i][j] = malloc(65 * sizeof *tableau[i][j] tu alloues 65 "étoile tableau[i][j]" or "étoile tableau[i][j]" c'est un char donc équivalent à ta dernière écriture tableau[i][j] = malloc(65 * sizeof char)).
    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]

  12. #12
    Membre régulier
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    210
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Avril 2007
    Messages : 210
    Points : 91
    Points
    91
    Par défaut
    Je n'ai que 2 mots à dire : grand merci !

    En effet, les explications sont très claires et éducatives.

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

Discussions similaires

  1. Réponses: 7
    Dernier message: 09/12/2014, 22h24
  2. Problème de réallocation de la mémoire
    Par dot-_-net dans le forum C++
    Réponses: 16
    Dernier message: 18/05/2008, 23h18
  3. problème our passer des string dans tableau d'int
    Par Battosaiii dans le forum C++
    Réponses: 9
    Dernier message: 15/07/2004, 17h42
  4. Problème lors du EXTEND d'un tableau
    Par banana31 dans le forum Oracle
    Réponses: 14
    Dernier message: 10/02/2004, 10h58
  5. Réponses: 25
    Dernier message: 16/07/2003, 20h41

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