Мне нужен Ваш совет относительно этой части кода: опции полей таблицы [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;
}
Проблема заключается в следующем:
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 в данном случае) не является константой, вам нужно отслеживать его самостоятельно, так как иначе вы не сможете узнать, сколько раз нужно выполнить цикл при освобождении.
Я собираюсь добавить к ответу Адама здесь , потому что это, вероятно, не поместится в комментарии. Адам совершенно прав. Я подозреваю, что ваша функция 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);
Надеюсь, что это даст вам еще несколько идей, Адам, не стесняйтесь редактировать любое / все это в своем ответе, если это необходимо, это в любом случае исходит из вашего ответа.
У вас должно быть столько же бесплатных
s, сколько у вас иметь malloc
s.
В вашем коде вы выделяете массив указателей, но не выделяете память для отдельных элементов массива, на которые они указывают. Но ваш код освобождения написан так, как будто вы это сделали.