выделение памяти для указателя и безопасное их освобождение на языке c - PullRequest
1 голос
/ 02 августа 2020

Хотя это кажется очень базовым c и повторяющимся вопросом, но я не нашел подобного вопроса.

Итак, я хочу создать структуру, содержащую некоторые указатели. При инициализации я выделяю им память, но не присваиваю им новые значения.

вот моя структура

typedef struct my_special_struct{
struct my_special_struct *ptr1;
struct my_special_struct *ptr2;
int val;
}my_special_struct;

и вот функция инициализации

my_special_struct *create_struct(int value,struct my_special_struct pointer1){
    my_special_struct *ptr;
    ptr = (my_special_struct *)malloc(sizeof(my_special_struct));
    ptr->val = value;
    ptr->ptr1 = (my_special_struct *)malloc(sizeof(my_special_struct));
    ptr->ptr1 = pointer1;
    ptr->ptr2 = (my_special_struct *)malloc(sizeof(my_special_struct));
    ptr->ptr2 = NULL;

    return ptr;
}

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

my_special_struct *add_ptr2(struct my_special_struct ptr,struct my_special_struct pointer2){
    ptr->ptr2 = pointer2;
    return ptr;
}

В конце кода я хочу освободить все назначенные указатели, вот функция

void delete_struct(struct my_special_struct ptr){
   if (ptr->ptr1 != NULL){
          delete_struct(ptr->ptr1);
      }
   else{
          free(ptr->ptr1);
      }
   if (ptr->ptr2 != NULL){
          delete_struct(ptr->ptr2);
      }
   else{
          free(ptr->ptr2);
      }
   free(ptr);

}

Итак, мои вопросы:

1- должен ли я назначить NULL для ptr2 в функции create_struct, или достаточно просто выделения памяти?

2- сделать безопасное освобождение памяти в функции delete_struct?

3- если я вызвал функцию delete_struct(ptr->ptr2); и попытался удалить только ptr2, какое будет значение ptr -> ptr2? и что именно будет, когда я позвоню delete_struct(ptr);?

1 Ответ

0 голосов
/ 02 августа 2020

На первый взгляд, это вопрос о двоичном дереве.

  1. Для ptr2, как отмечено в комментариях, достаточно назначить указатель NULL. Выделение памяти просто приведет к потере («утечке») памяти.
  2. Пример кода с использованием рекурсивной версии delete_struct. Таким образом, эта функция должна либо удалить дочерние элементы, либо удалить текущий элемент (но не оба сразу). Также хорошей практикой является использование указателей удаления NULL, чтобы избежать случайного повторного использования.
  3. Вызов 'free' не изменяет значение указателя, он отмечает область памяти, доступную для повторного использования.

альтернативное удаление + очистка указателя.

void delete_struct(struct my_special_struct ptr){
   if ( ptr != NULL ) {
       delete_struct(ptr->ptr1);
       ptr->ptr1 = NULL ;

       delete_struct(ptr->ptr2);
       ptr->ptr2 = NULL ;

       free(ptr);
   }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...