Erreur de Segmentation (Core Dumped)

Résolu/Fermé
Celebrations - 16 déc. 2015 à 16:55
mamiemando Messages postés 33077 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 18 avril 2024 - 17 déc. 2015 à 10:35
Bonjour,
Je suis actuellement en train d'essayer d'additionner deux valeurs dans un tableau à deux dimensions, sauf qu'à l’exécution j'ai "Erreur de segmentation (core dumped)" et je ne vois pas d'où le segfault provient.
Serait-il possible d'avoir un peu d'aide, je suis débutant. :p

Voici mon code :

int     array_2d_sum(int **arr, int nb_rows, int nb_cols)
{
  int   i;
  int   j;
  int   **arr2;
  int   k;
  int   l;

  i = 0;
  j = 0;
  k = 0;
  l = 0;
  arr2 = malloc(sizeof(int) * (nb_cols + nb_rows));
  while (i < nb_rows && j < nb_cols)
    {
      arr2[k][l] == arr[i][j] + arr[i + 1][j + 1];
      my_putnbr(arr2[k][l]);
      my_putchar('\n');
      i++;
      j++;
      k++;
      l++;
    }
}

int     main()
{
  int   arr[4][4] = {{1, 2, 3, 4}, {1, 2, 3, 4}};

  array_2d_sum(arr, 4, 4);
}

(Bien sûr j'ai mis l'include stdlib.h pour le malloc et les fonctions putchar et putnbr fonctionnent très bien)
Merci à vous

A voir également:

1 réponse

mamiemando Messages postés 33077 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 18 avril 2024 7 749
Modifié par mamiemando le 16/12/2015 à 17:45
Bonjour,

Cette erreur est normale, et tu peux voir en lançant ton programme avec un débogueur (par exemple
gdb
sous linux) que cette erreur survient quand tu evalue arr[i][j] :

gcc -g programme.c -o executable
gdb ./executable
r
bt


Ton erreur vient de la manière dont tu alloues ta matrice et la manière dont tu accèdes à la case (i, j) :
1) une matrice de dimension (m, n) a exactement m * n cases, où m est le nombre de lignes et n le nombre de colonnes : fondamentalement tu n'as donc pas alloué la bonne quantité de mémoire ave ton
malloc
.
2) un seul
malloc
revient à allouer un tableau 1D, aussi complexe soit le calcul fait dans le malloc. Si tu as alloué n cases de type T et que tu manipules l'adresse de ce tableau, celui ci est indexé de 0 à n-1 inclus. Donc si tu as alloué m * n cases, tu accèdes aux différents éléments avec les valeur de 0 à ((m * n) - 1)

Il faut donc faire un choix :

1) soit tu alloues bien m * n cases dans un seul vecteur, et ton coefficient (i, j) est accessible via le calcul :
matrice[n*j + i]
, quitte à définir une fonction du genre :

typedef int * matrice_t;

int matrice_get(matrice_t matrice, unsigned i, unsigned j) {
  return matrice[n*j + i];
}

int ** matrice_create(unsigned m, unsigned n) {
  return malloc(m * n * sizeof(int));
}

void matrice_free(matrice_t matrice) {
  free(matrice);
}


2) soit tu alloues un tableau de ligne, et chaque ligne de ta matrice :

typedef int ** matrice_t;

int matrice_get(matrice_t matrice, unsigned i, unsigned j) {
  return matrice[i][j];
}

int ** matrice_create(unsigned m, unsigned n) {
  unsigned i, j;
  int ** matrice = malloc(m * sizeof(int *));
  for(i = 0; i < m; ++i) {
    matrice[i] = malloc(n * sizeof(int));
  }
  return matrice
}

void matrice_free(matrice_t matrice) {
  for(i = 0; i < m; ++i) {
    free(matrice[i]);
  }
  free(matrice);
}


Bonne chance
2
Celebrations
16 déc. 2015 à 17:50
Merci à toi.. ^^
0
mamiemando Messages postés 33077 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 18 avril 2024 7 749
17 déc. 2015 à 10:35
De rien :-)

Je profite de ce fil de discussion pour souligner quelques points fondamentaux sur les pointeurs, et qui sont généralement très mal expliqués (selon moi).

Les tableaux en C sont une "illusion". Ce n'est qu'un jeu d'écriture, car en fait, tout est adresse mémoire et la machine ne raisonne que comme ça, il n'y a pas de notion de tableau a proprement parlé (par opposition par exemple aux
std::vector<T>
du C++).

En réalité,
tab[i]
signifie
*(tab + i)
: à partir de l'adresse de
tab
, on se décale de
i
cases, la taille d'une case étant déterminée par le type du pointeur.

En particulier,
tab[0] == *tab
. Et
tab + 1
revient à se placer juste après cette première "case", c'est-à-dire sur le second élément du tableau. On comprend dès lors pourquoi en C les "tableaux" sont "indexés" à partir de 0.

Ainsi, si mon pointeur est un
T *
se décaler de
i
cases revient à se décaler de
i * sizeof(T)
.

Si on regarde la deuxième version de matrice que je te proposais, on voit que ce
T
peut tout à fait lui même être un type de pointeur, car une pointeur n'est qu'une adresse et à donc une taille bien connue (32 bits sur une architecture 32 bits, 64 sur une architecture 64 bits). Ça donc du sens d'utiliser un opérateur
[ ]
sur un
int **
("tableau" qui stocke des adresses de type
int *
).

Par contre, ça n'a pas de sens d'appliquer cet opérateur sur un pointeur
void *
: ce type est utilisé pour désigner une adresse générique, mais on ne connaît pas la nature (et donc la taille) de l'objet ainsi référencé. Il est dès lors impossible de donner un sens à
tab + 1
, donc à
tab + i
, et donc a fortiori à
tab[i]
. C'est pourquoi l'opérateur
+
et
[ ]
ne peut pas être appliqué à un tel pointeur.
2