Освобождение выделенной памяти: realloc() vs. free()

поэтому у меня есть часть памяти, выделенная с помощью malloc() и позже измененная с помощью realloc().

В какой-то момент в моем коде я хочу его опорожнить, я имею в виду, по сути, дать ему память 0. Что-то, что было бы интуитивно сделано с помощью realloc(pointer,0). Я читал здесь, что это реализация определена и не должна использоваться.

Должен ли я использовать free(), а затем сделать еще один malloc()?

Ответ 1

Это зависит от того, что вы имеете в виду: если вы хотите очистить используемую память, но все еще имеете доступ к этой памяти, то вы используете memset(pointer, 0, mem_size); для повторной инициализации указанной памяти до нулей.
Если вам больше не нужна эта память, вы просто вызываете free(pointer);, который освободит память, поэтому ее можно использовать в другом месте.

Использование realloc(pointer, 0) может работать как free в вашей системе, но это стандартное поведение не. realloc(ptr, 0) не указывается стандартами C99 или C11 как эквивалент free(ptr).

realloc(pointer, 0) не эквивалентен free(pointer).

Стандарт (C99, §7.22.3.5):

The realloc function
Synopsis
1
#include <stdlib.h>
void *realloc(void *ptr, size_t size);

Description
2 The realloc function deallocates the old object pointed to by ptr and returns a
pointer to a new object that has the size specified by size. The contents of the new
object shall be the same as that of the old object prior to deallocation, up to the lesser of
the new and old sizes. Any bytes in the new object beyond the size of the old object have
indeterminate values.
3 If ptr is a null pointer, the realloc function behaves like the malloc function for the
specified size. Otherwise, if ptr does not match a pointer earlier returned by a memory
management function, or if the space has been deallocated by a call to the free or
realloc function, the behavior is undefined. If memory for the new object cannot be
allocated, the old object is not deallocated and its value is unchanged.
Returns
4
The realloc function returns a pointer to the new object (which may have the same
value as a pointer to the old object), or a null pointer if the new object could not be
allocated.

Как вы можете видеть, он не указывает специальный случай для вызовов realloc, где размер равен 0. Вместо этого он только заявляет, что указатель NULL возвращается при ошибке выделения памяти и указатель во всех остальных случаях. Тогда указатель, указывающий на 0 байтов, будет жизнеспособным вариантом.

Чтобы процитировать связанный вопрос:

Более интуитивно, realloc "концептуально эквивалентен" для malloc + memcpy + free на другом указателе, а malloc-ing 0-байтовый блок памяти возвращает либо NULL либо уникальный указатель, а не для хранения чего-либо (вы запросили 0 байтов), но все равно освобождаетесь. Таким образом, нет, не используйте realloc, как это, он может работать с некоторыми реализациями (а именно с Linux), но это, безусловно, не гарантируется.

Как еще один ответ на этот связанный вопрос, поведение realloc(ptr, 0) явно определяется как реализация, определенная в соответствии с текущим стандартом C11:

Если размер запрашиваемого пространства равен нулю, поведение определяется реализацией: возвращается нулевой указатель или поведение такое, как если бы размер был некотором ненулевым значением, за исключением того, что возвращаемый указатель не должен использоваться для доступ к объекту

Ответ 2

realloc() используется для увеличения или уменьшения памяти, а не для освобождения памяти.

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

Ответ 3

Используйте free(pointer); pointer = 0 вместо realloc(pointer, 0).

Ответ 4

Я не думаю, что вы имеете в виду "пусто"; это означало бы "установить его на какое-то определенное значение, которое я считаю пустым" (часто все биты нуль). Вы имеете в виду бесплатное или де-распределение.

На странице руководства говорится:

Если ptr равно NULL, тогда вызов эквивалентен malloc(size), для всех значений size; если size равно нулю, а ptr не NULL, тогда вызов эквивалентен free(ptr).

Традиционно вы можете использовать realloc(ptr, 0); как синоним для free(ptr);, так же, как вы можете использовать realloc(NULL, size); как синоним для malloc(size);. Я бы не рекомендовал его, но это немного запутанно, а не то, как люди ожидают его использования.

Однако, в настоящее время в современном C определение изменилось: теперь realloc(ptr, 0); освободит старую память, но не определило, что будет сделано дальше: она определена в соответствии с реализацией.

Итак: не делайте этого: используйте free(), чтобы выделить выделение памяти, и пусть realloc() используется только для изменения размера на что-то ненулевое.

Ответ 5

void* realloc (void* ptr, size_t size);

В C90:

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

В C99:

Если размер равен нулю, возвращаемое значение зависит от конкретной реализации библиотеки: оно может быть либо нулевым указателем, либо другим местом, которое не должно быть разыменовано.

Ответ 6

Используйте free(), чтобы освободить, чтобы освободить динамически выделенную память.

Хотя в прежних документах указано, что realloc(p, 0) эквивалентно free(p), последний документация POSIX явно заявляет, что это не так:

Предыдущие версии явно разрешали вызов realloc (p, 0), чтобы освободить пространство, на которое указывает p, и вернуть нулевой указатель. Хотя это поведение можно интерпретировать как разрешенное этой версией стандарта, комитет языка C указал, что эта интерпретация неверна.

И еще:

Приложения должны предполагать, что если realloc() возвращает нулевой указатель, пространство, на которое указывает p, не было освобождено.

Ответ 7

Я бы использовал realloc, чтобы дать указателю больше или меньше памяти, но не пустить его. Чтобы очистить указатель, я бы использовал бесплатно.