Если два указателя указывают на один и тот же адрес памяти, нужно ли вам использовать free (ptr) один или два раза? - PullRequest
3 голосов
/ 08 ноября 2019

Скажем, у нас есть структура ...

struct node{
    int data;
    struct node *next;
};

struct node *new_node = malloc(sizeof(node));

struct node *temp_node = new_node;

Если я использую free ...

free(temp_node);

Также свободен new_node (так как адрес больше не существует) илиnew_node просто указывает на NULL (в этом случае мне также потребуется освободить new_node)?

Приветствия!

Ответы [ 6 ]

2 голосов
/ 08 ноября 2019

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

При malloc возвращается указатель на выделенную часть памяти, которая выглядит какэто:

             +--------+
             |        |
new_node --> | 0x1000 |
             |        |
             +--------+

Если 0x1000 является начальным адресом этого блока памяти, это то, на что new_node указывает (т.е. new_node == 0x1000).

Когда вы назначаете *От 1012 * до temp_node, temp_node указывает на один и тот же блок памяти (т. Е. temp_node == 0x1000):

             +--------+
             |        |
new_node --> | 0x1000 | <-- temp_node
             |        |
             +--------+

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

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

PS: указатель Free'd может указывать или не указывать на NULL впоследствии - это просто неопределенное поведение длядоступ к свободной памяти.

1 голос
/ 08 ноября 2019

Несколько замечаний по коду

  • Объявления struct *next и struct *temp_node указывают на неназванную структуру, у которой нет экземпляров.
  • node это просто тег структуры используется для именования структуры и не может использоваться в выражениях, подобных этому malloc(sizeof(node)).

Если это то, что вы изначально имели в виду:

struct node{
  int data;
  struct node *next;
};
struct node * new_node = malloc(sizeof(struct node));
struct node * temp_node = new_node;

Тогда ответы, предоставленные перед этим постом, абсолютно точны.

1 голос
/ 08 ноября 2019

Для одного адреса памяти вам нужно всего лишь один раз вызвать free.

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

1 голос
/ 08 ноября 2019

Поскольку вы освобождаете память, и я вижу здесь только один malloc, вам следует только free() один раз.

В общем, для каждого malloc должен быть один и только один free. В противном случае вы получите двойную ошибку free.

1 голос
/ 08 ноября 2019

Способ думать таков: указатели указывают на область памяти. free() возвращает память, на которую указывает указатель, обратно в систему. Таким образом, если у вас есть два указателя - один раз free вызывается, память возвращается в систему. У вас еще есть два указателя. И они все еще указывают на одну и ту же область памяти. Просто сейчас это не ваша память, а системная:)

Короче говоря - free столько раз, сколько вы malloc 'd.

1 голос
/ 08 ноября 2019

Существует множество исключений, но, как правило, должен быть ровно один вызов free для каждого вызова malloc.

Когда вы присваиваете одну переменную-указатель другой, выкопирование значения указателя - вы не выделяете больше памяти. Таким образом, копия указателя не подразумевает необходимость повторного вызова free.

...