Partage
  • Partager sur Facebook
  • Partager sur Twitter

erreur parcour tableau 2D allocation dynamique

erreur segmentation fault lors du parcour d'un tableau 2D

Sujet résolu
    5 février 2023 à 14:19:33

    Bonjour, je me permet de poster une question suite à un probleme auxquel je suis confronté et pour lequel je necomprends pas bien mon erreur :

    Mon objectif est de manipuler un tableau créé à partir de pointeurs.

    Pour ce faire, ma fonction main appelle une fonction (initialisationTab).

    Cette fonction initialise un tableau en prenant en paramètre le nombre de ligne et de colonne.

    Une fois le tableau initialisé, je parcours le tableau case par case.Dans chaque case j'écris la valeur 1, puis je gère l'affichage du tableau.

    le programme semble fonctionner jusqu'a la 5 eme ligne de mon tableau, cependant à la sixième je suis gratifié d'un magnifique segmentation fault...

    voici mon code :

    #include <stdio.h>
    #include <stdlib.h>
    
    int** initialisationTab(int ligne ,int colonne);
    
    int main(int argc, char *argv[])
    {
        int **tab = initialisationTab(10, 10);
    
        // valorisation et affichage
        for (int i = 0; i < 10; i++)
        {
            printf("||");//affichage en début de chaque ligne
            for (int j = 0; j < 10; j++)
            {
                tab[i][j] = 1;//on valorise la case du tableau a 1
                if (j != 0)
                {
                     printf(" | ");//affichage entre chaque valeur de la ligne parcourue
                }
                printf("%d", tab[i][j]);
                if (j == 9)
                {
                    printf("||\n");//affichage en fin de ligne 
                }
            }
        }
    
        //on libère la mémoire
        for(int k = 0; k < 100; k++)
        {
            free(tab[k]);
        }
        free(tab);
    
        return 0;
    }
    
    int** initialisationTab(int ligne ,int colonne)
        {
            int **tab = malloc(ligne*sizeof(int));
    
            for (int i = 0; i < ligne; i ++)
            {
                tab[i] = malloc(colonne*sizeof(int));
            }
            return tab;
        }

    je ne comprend pas bien pourquoi tout semble fonctionner jusquà cette fameuse 6eme ligne...

    si quelqu'un peut m'aider à comprendre ce qu'il se passe je suis preneur.

    -
    Edité par Sim29 5 février 2023 à 14:28:28

    • Partager sur Facebook
    • Partager sur Twitter
      5 février 2023 à 15:17:01

      Bonjour,

      Je vois une erreur à la ligne 32 dans la fonction main. Retiens bien qu' il doit y avoir autant de free qu' il y a de malloc réussis.

      Dans ta fonction 'initialisationTab' tu fais un malloc pour préparer les futures colonnes par une allocation de 10 lignes et après tu fais 'lignes' fois des mallocs (10 précisement ). Or pour libérer la mémoire allouée ligne 45, tu fais 100 free ! (alors que tu devrait en faire 10, soit autant que le nombre de malloc à la ligne 45. Le free correspondant au malloc de la ligne 41 est lui est bon cela dit.:)

      -
      Edité par Warren79 5 février 2023 à 15:18:43

      • Partager sur Facebook
      • Partager sur Twitter

      Mon site web de jeux SDL2 entre autres : https://www.ant01.fr

        5 février 2023 à 15:37:46

        Bonjour,

        En fait, il y a aussi une erreur ligne 41. Ce qui est alloué se sont des pointeurs sur des int pas des int.

                int **tab = malloc( ligne * sizeof(*int) );
        // ou
                int **tab = malloc( ligne * sizeof(*tab) );
        
        • Partager sur Facebook
        • Partager sur Twitter

        En recherche d'emploi.

          5 février 2023 à 17:45:57

          Ça ne serait pas plutôt:
              int **tab = malloc(ligne * sizeof(*int));
          int* au lieu de *int

          Le seg fault est causé parce que tu ne réserves pas assez de mémoire pour tes 10 pointeurs.

          En général, un pointeur occupe 8 octets alors qu'un int en occupe seulement 4.

          -
          Edité par PierrotLeFou 5 février 2023 à 17:50:41

          • Partager sur Facebook
          • Partager sur Twitter

          Le Tout est souvent plus grand que la somme de ses parties.

            5 février 2023 à 18:36:54

            PierrotLeFou a écrit:

            Ça ne serait pas plutôt:
                int **tab = malloc(ligne * sizeof(*int));
            int* au lieu de *int

            Le seg fault est causé parce que tu ne réserves pas assez de mémoire pour tes 10 pointeurs.

            En général, un pointeur occupe 8 octets alors qu'un int en occupe seulement 4.

            En effet, j'ai écris un peu vite. Et aussi d'accord sur la cause du seg fault.
            • Partager sur Facebook
            • Partager sur Twitter

            En recherche d'emploi.

              5 février 2023 à 19:22:16

              Pour réserver un tableau de dim 2 d'entiers par exemple, une autre solution est de ne faire que 2 allocations

              • la première pour réserver de la place pour tous les entiers
              • la seconde pour réserver le tableau de pointeurs qui dit où commence chaque ligne
              Intérêt par rapport à l'allocation "par ligne" :
              • comme malloc arrondit chaque demande à un multiple de 64 octets (de mémoire), et y ajoute de l'espace pour chaîner les blocs entre eux, il y aura moins de perte de place
              • qui plus est, on a la garantie que les données sont consécutives en mémoire, la "localité" peut avoir un impact fort sur l'utilisation des caches. Alors qu'avec l'autre système, les lignes peuvent être éparpillées.
              • seulement 2 d'allocations à faire => moins d'appels à l'allocateur => code plus court et plus rapide.
              #include <stdio.h>
              #include <stdlib.h>
              
              #define NB_LIGNES 10
              #define NB_COLONNES 8
              
              int** allouer_tableau(int nb_lignes, int nb_colonnes) {
              	int *contenu = malloc(nb_lignes * nb_colonnes * sizeof(int));
              	int **tableau = malloc(nb_lignes * sizeof(int *));
              	for (int ligne = 0; ligne < nb_lignes; ligne++) {
              		tableau[ligne] = & contenu[ligne * nb_colonnes];
              	}
              	return tableau;
              }
              
              
              void liberer_tableau(int **tableau) {
              	free(tableau[0]);
              	free(tableau);
              }
              
              void afficher_tableau(int nb_lignes, int nb_colonnes,
              					  int **tableau)
              {
              	for (int ligne = 0; ligne < nb_lignes; ligne++)
                  {
                      printf("||");
                      for (int colonne = 0; colonne < nb_colonnes; colonne++)
                      {
                          tableau[ligne][colonne] = 1;
                          printf(" %d |", tableau[ligne][colonne]);
              		}
              		printf("|\n");
              	}
              }
              
              int main(int argc, char *argv[])
              {
                  int **tableau = allouer_tableau(NB_LIGNES, NB_COLONNES);
              
                  afficher_tableau(NB_LIGNES, NB_COLONNES, tableau);
                  liberer_tableau(tableau);
              
              	return 0;
              }
               
              

              Exécution et vérification : pas de fuite.

              $ valgrind ./alloctab 
              ==30452== Memcheck, a memory error detector
              ==30452== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
              ==30452== Using Valgrind-3.16.1 and LibVEX; rerun with -h for copyright info
              ==30452== Command: ./alloctab
              ==30452== 
              || 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 ||
              || 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 ||
              || 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 ||
              || 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 ||
              || 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 ||
              || 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 ||
              || 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 ||
              || 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 ||
              || 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 ||
              || 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 ||
              ==30452== 
              ==30452== HEAP SUMMARY:
              ==30452==     in use at exit: 0 bytes in 0 blocks
              ==30452==   total heap usage: 3 allocs, 3 frees, 1,424 bytes allocated
              ==30452== 
              ==30452== All heap blocks were freed -- no leaks are possible
              ==30452== 
              ==30452== For lists of detected and suppressed errors, rerun with: -s
              ==30452== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
              



              -
              Edité par michelbillaud 5 février 2023 à 19:26:29

              • Partager sur Facebook
              • Partager sur Twitter
                5 février 2023 à 22:05:05

                woaw ! merci à tous probleme résolu. je n'ai plus qu'a me poser calmement pour bien comprrendre les alternatives que vous m'avez envoyé.

                merci pour votre temps. je devenais fou a relire mon petit bout de code ^^

                merci encore !

                • Partager sur Facebook
                • Partager sur Twitter

                erreur parcour tableau 2D allocation dynamique

                × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                • Editeur
                • Markdown