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

Vue hybride

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

    Informations forums :
    Inscription : Avril 2007
    Messages : 211
    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 expérimenté

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

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Septembre 2012
    Messages : 329
    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 expérimenté

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

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Septembre 2012
    Messages : 329
    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 confirmé
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Décembre 2015
    Messages
    1 599
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    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 599
    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 confirmé
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 771
    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 771
    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 |

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

    Informations professionnelles :
    Activité : Chef de projet NTIC

    Informations forums :
    Inscription : Juillet 2020
    Messages : 352
    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.

  7. #7
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 835
    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 835
    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]

+ 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