Передача указателей и выделение памяти приводит к segfault

#c #pointers #segmentation-fault #malloc

#c #указатели #ошибка сегментации #malloc

Вопрос:

Я пишу программу на C, но у меня возникли небольшие проблемы с указателями и правильным распределением памяти. Вот мой код:

 void read_file(char* file_name, float***** data, unsigned char**** flagged, 
              unsigned char**** initial_flagged)
{
  int nr_stations;
  int nr_times;
  int nr_subbands;
  int nr_subbands_in_file;
  int nr_channels;
  int nr_polarizations;
  int i,j,k;
  int err;

  /*Unnecessary code omitted*/


 //allocate memory for data and flags.

  *data = (float****) malloc(sizeof(float***) * nr_times);
  if(*data == NULL){
    perror("Error allocating memory for data buffer:");
    exit(1);
  }
  *flagged = (unsigned char***) malloc(sizeof(unsigned char **) * nr_times);
  if(*flagged == NULL){

    perror("Error allocating memory for flag buffer:");
    exit(1);
  }
  *initial_flagged = (unsigned char***) malloc(sizeof(unsigned char **) * nr_times);
  if(*initial_flagged == NULL){
    perror("Error allocating memory for flag buffer:");
    exit(1);
  }

  for(i=0;i<nr_times;i  ){
    *data[i] = (float ***) malloc(sizeof(float**) * nr_subbands);
    if(*data[i] == NULL){
      perror("Error allocating memory for data on time");
      exit(1);
    }
    *flagged[i] = (unsigned char **) malloc(sizeof(unsigned char *) * nr_subbands);
    if(*flagged[i] == NULL){
      perror("Error allocating memory for flags on time");
      exit(1);
    }
    *initial_flagged[i] = (unsigned char **) malloc(sizeof(unsigned char *) 
    * nr_subbands);
    if(*initial_flagged[i] == NULL){
      perror("Error allocating memory for initial_flags on time");
      exit(1);
    }

    for(j=0;j<nr_subbands;j  ){
      *data[i][j] = (float **) malloc(sizeof(float*) * nr_polarizations);
      if(*data[i][j] == NULL){
        perror("Error allocating memory for data on subband at time");
        exit(1);
      }

      for(k=0;k<nr_polarizations;k  ){
        *data[i][j][k] = (float *) malloc(sizeof(float) * nr_channels);
        if(*data[i][j][k] == NULL){
          perror("Error allocating memory for data on on polarization on subband at time ");
          exit(1);
        }
        memset(*data[i][j][k], 0, sizeof(float) * nr_channels);
      }
      *flagged[i][j] = (unsigned char*) malloc(sizeof(unsigned char) * nr_channels);
      if(*flagged[i][j] == NULL){
        perror("Error allocating memory for flags on subband at time");
        exit(1);
      }
      *initial_flagged[i][j] = (unsigned char*) malloc(sizeof(unsigned char) *
      nr_channels);
      if(*initial_flagged[i][j] == NULL){
        perror("Error allocating memory for initial flags on subband at time");
        exit(1);
      }
      memset(*flagged[i][j], 0, sizeof(unsigned char) * nr_channels);
      memset(*initial_flagged[i][j], 0, sizeof(unsigned char) * nr_channels);
    }
  }

int main(int argc, char** argv){
  float**** data = NULL;
  unsigned char*** flagged = NULL;
  unsigned char*** initial_flagged = NULL;

  if(argc != 2){
    printf("Usage: flagger <filename>n");
    exit(1);
  }

  read_file(argv[1], amp;data, amp;flagged, amp;initial_flagged); 
  printf("data = %pn", data);
  return 0;


}
  

Когда я запускаю этот код, он прерывается на

*data[i][j][k] = (float *) malloc(sizeof(float) * nr_channels);

Однако, когда я не передаю указатели на data, flagged или initial_flagged в метод, но объявляю их в области действия функции, это работает нормально, но я не могу использовать эти массивы вне функции.

Комментарии:

1. float***** , это первый раз, когда я вижу пять звезд.

2. @YuHao Есть ли лучшие способы передачи четырехмерных массивов? 🙂

3. @Linus здравый смысл, structs , typedef , использование одномерного массива с лучшей индексацией и т.д….

Ответ №1:

В C оператор разыменования (ie *) имеет более низкий уровень или приоритет, чем операторы подписки на массив (ie []).

Следовательно, операция *data[i][j] эквивалентна *(data[i][j]) . В вашей программе это привело к ошибке segfault, потому что она интерпретировала значение в data[i][j] как адрес и пыталась получить доступ к данным, хранящимся по этому адресу, в то время как на самом деле это было значение с плавающей точкой.

Итак, в этом случае вы ДОЛЖНЫ использовать круглые скобки, например (*data)[i][j] .

Смотрите Предшествие оператора C / C

Ответ №2:

Хорошо, итак, я разобрался с этим сам (полагаю, отладка rubber duck). По-видимому, существует разница между *data[i][j] и (*data)[i][j]. Второе — это то, что я имел в виду, и оно заставляет мой код работать правильно!