Почему я получаю ошибку сегмента (многомерный массив C) - PullRequest
0 голосов
/ 02 февраля 2012

Я не могу понять, что я делаю неправильно.

int main(int argc, char **argv) {
  int height = 4, width = 6;
  int **map;
  map = (int **)(malloc(height * sizeof(int*)));
  for(i = 0; i < height; i++) {
    map[i] = (int *)(malloc(width * sizeof(int)));
  }
  fill_map(&map, height, width);
}

void fill_map(int ***map, int height, int width) {
  int i, k, character;
  for(i = 0; i < height; i++) {
    k = 0;
    while((character = getchar()) != '\n') {
        *map[i][k] = character;
        k++;
    }
  }
}

Я получаю ошибку в fill_map во внутреннем цикле while, почему?

Ответы [ 6 ]

3 голосов
/ 02 февраля 2012

Не отправлять и не отображать в функцию, изменить прототип для получения (int ** map) или использовать (* map) [i] [k]. Это связано с тем, что оператор косвенности * имеет более низкий приоритет, чем оператор [].

1 голос
/ 02 февраля 2012

Как вы ожидаете, чтобы завершить цикл while, вы когда-нибудь сохраняли "\ n" в вашем массиве? Вы только что выделили память и пытаетесь путешествовать по ней. Он никогда не находит "\ n", поэтому пока цикл выходит из области памяти, и вы получаете ошибку сегментации.

0 голосов
/ 02 февраля 2012

То, что вы используете, это не двумерный массив, а просто его симуляция. В современном C, начиная с C99, с «изменяемыми типами» ваша задача так же проста:

#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>

void fill_map(size_t height, size_t width, char map[height][width]) {
  int character;
  for(size_t i = 0; i < height; i++) {
    for (size_t k = 0; k < width; k++) {
      if ((character = getchar()) != '\n')
        map[i][k] = character;
      else break;
    }
  }
}

int main(int argc, char **argv) {
  size_t height = 4, width = 6;
  char (*map)[width] = malloc(sizeof(char[height][width]));
  fill_map(height, width, map);
}
  • сначала передайте размеры матрицы, затем вы можете просто использовать их в объявлении параметра матрицы
  • используйте size_t для индексации
  • не произносите возвращение malloc
  • будьте осторожны с границами вашей петли
  • также лучше проверить конец файла (домашнее задание)
0 голосов
/ 02 февраля 2012

Ваша ошибка сегментации происходит из-за неправильной разыменования map;Вы должны написать это как (*map)[i][k] вместо *map[i][k].Хотя в вызове & лучше не указывать fill_map и соответствующим образом настроить прототип:

fill_map(map, height, width);
...
void fill_map(int **map, int height, int width)
{
  ...
  map[i][k] = character;
  ...
}

Вы можете очистить malloc вызовы следующим образом:

map = malloc(height * sizeof *map);

и

map[i] = malloc(width * sizeof *map[i]);

Приведения не нужны в C 1 и считаются плохой практикой.


1 Это не истина в C ++;требуется приведение, но если вы пишете C ++, вы должны использовать new вместо malloc.
0 голосов
/ 02 февраля 2012

Сначала - прислушайтесь к советам «prmg» и «perreal».

Не приводить возвращаемое значение malloc. malloc возвращает void * и приведение не требуется. Если вы забудете #include <stdlib.h>, вы сами создадите себе проблему.

map = malloc( height * sizeof *map );
0 голосов
/ 02 февраля 2012

Я бы использовал GDB или другой отладчик.Скомпилируйте программу с символами отладки, запустите ее там, и она сообщит вам строку, на которой вы используете segfaulting.

...