как правильно освободить символ ** таблица в C

Мне нужен Ваш совет относительно этой части кода: опции полей таблицы [0], опции [1] и т.д...., кажется, не освобождены правильно. Спасибо за Ваши ответы

int main()
{
  ....
  char **options;
  options = generate_fields(user_input);
  for(i = 0; i < sizeof(options) / sizeof(options[0]); i++)  {
    free(options[i]);
    options[i] = NULL;
  }

  free(options);
}

char ** generate_fields(char *) 
{
   char ** options = malloc(256*sizeof(char *));
   ...
   return options;

}
6
задан Zenet 20 March 2010 в 17:20
поделиться

3 ответа

Проблема заключается в следующем:

for(i = 0; i < sizeof(options) / sizeof(options[0]); i++)

options - это тип указателя, а не тип массива, поэтому sizeof(options) всегда будет одинаковым (обычно 4 байта на 32-битной машине или 8 байт на 64-битной машине), поэтому sizeof(options)/sizeof(options[0]) почти всегда будет равен 1.

Ключ в том, чтобы всегда освобождать память так же, как вы malloc'ed ее. Так, если вы malloc двумерный массив, а затем malloc серию одномерных массивов, то при освобождении нужно делать все наоборот:

char ** generate_fields(char *) 
{
   char ** options = malloc(256*sizeof(char *));
   for(int i = 0; i < 256; i++)
       options[i] = malloc(some_size);
   return options;
}

void free_fields(char ** options)
{
    for(int i = 0; i < 256; i++)
        free(options[i]);
    free(options);
}

Обратите внимание, что если размер (256 в данном случае) не является константой, вам нужно отслеживать его самостоятельно, так как иначе вы не сможете узнать, сколько раз нужно выполнить цикл при освобождении.

16
ответ дан 8 December 2019 в 04:08
поделиться

Я собираюсь добавить к ответу Адама здесь , потому что это, вероятно, не поместится в комментарии. Адам совершенно прав. Я подозреваю, что ваша функция generate_fields, возможно, действительно получает ввод от пользователя, я не уверен. В любом случае есть два подхода к этому:

char ** generate_fields(char *, int num_fields, int size_of_field) 
{
   char ** options = malloc(num_fields*sizeof(char *));
   for(int i = 0; i < num_fields; i++)
       options[i] = malloc(size_of_field);
   return options;
}

и соответствующая свободная функция, которую я опущу для краткости. Вы можете видеть, что происходит - мы передаем количество полей и размер поля. Измените это так, как вам нужно.Другой вариант - передать генерируемые поля обратно в процедуру, которую она вызывает, исходя из размера массива. Я бы сделал что-то вроде этого:

int generate_fields(char** options) 
{
   int num_fields = 0;
   // somewhere here we get num_fields
   options = malloc(num_fields*sizeof(char *));
   for(int i = 0; i < num_fields; i++)
       options[i] = malloc(size_of_field);
   return num_fields;
}

И вы вызываете из main следующим образом:

int main()
{
    int sizeofarray = 0;
    char** fields;
    sizeofarray = generate_fields(fields);

Или, если вам не нравится эта нотация, вы всегда можете придерживаться того, что у вас было:

char** generate_fields(int* size) 

В качестве прототипа функции (на этот раз верните параметры и введите size = где-нибудь в коде и вызовите из main следующим образом:

int sizeofarray = 0;
char** options;
options = generate_fields(&sizeofarray);

Надеюсь, что это даст вам еще несколько идей, Адам, не стесняйтесь редактировать любое / все это в своем ответе, если это необходимо, это в любом случае исходит из вашего ответа.

3
ответ дан 8 December 2019 в 04:08
поделиться

У вас должно быть столько же бесплатных s, сколько у вас иметь malloc s.

В вашем коде вы выделяете массив указателей, но не выделяете память для отдельных элементов массива, на которые они указывают. Но ваш код освобождения написан так, как будто вы это сделали.

7
ответ дан 8 December 2019 в 04:08
поделиться
Другие вопросы по тегам:

Похожие вопросы: