Первый вопрос:
realloc(array, 0)
не эквивалентно free(array)
.
Стандарт (C99, §7.20.3.4 ¶1) гласит:
Функция realloc
освобождает старый объект, на который указывает ptr
, и возвращает указатель на новый объект, размер которого указан size
.
и не дает "особого случая" для size==0
; таким образом, вы получаете указатель на объект нулевого размера, но который потенциально все еще является объектом и все еще должен быть освобожден.
Интересно, я думаю, что realloc
может просто не сработать в таких обстоятельствах, возвращая NULL
; в этом случае в вашем коде происходит утечка памяти, поскольку при сбое realloc
он не освобождает исходный блок памяти, который вы ему передали (вот почему вы никогда не выполняете array = realloc(array, size)
, но всегда используете промежуточную переменную для проверки наличия NULL
во избежание утечек памяти).
На самом деле стандарт определяет size==0
поведение, определяемое реализацией, для всех функций выделения памяти, а не только для malloc
, как я помнил; таким образом, поведение определяется реализацией, как описано ниже:
Более интуитивно, realloc
«концептуально эквивалентно» malloc
+memcpy
+free
для другого указателя, а malloc
-обработка 0-байтового фрагмента памяти возвращает либо NULL
, либо уникальный указатель, который нельзя использовать для хранения чего-либо (вы спросили для 0 байт), но все еще должен быть free
ed. Так что нет, не используйте realloc
таким образом, он может работать в некоторых реализациях (а именно, в Linux), но это точно не гарантируется.
Кроме того, непонятно, как вы пришли к выводу, что free
не работает. Я могу придумать два способа убедить вас в этом:
- значение
array
и данных, на которые он указывает, не изменилось;
- выделенная память в диспетчере задач/
top
/во что бы то ни стало не уменьшается.
Для первого случая это нормально; когда вы освобождаете указатель, он не стирается волшебным образом — ваш указатель по-прежнему указывает туда, куда он указывал, но эта память больше не ваша — теперь она возвращается к среде выполнения C, которая, вероятно, повторно отдаст ее в будущем. malloc
. Вот почему эта штука называется "висячий указатель", и многие люди после free
устанавливают его на NULL
, чтобы избежать повторной записи в области памяти, которая уже была освобождена.
Что касается второго, то аллокаторы обычно не возвращают оперативную память немедленно (если только мы не говорим о действительно больших кусках памяти); идея состоит в том, что, вероятно, приложению скоро снова понадобится такая память, и сохранение этой памяти для текущего процесса может избежать непрерывных системных вызовов для получения/отдачи памяти от ОС. Поскольку системные утилиты для мониторинга обычно используемой памяти могут видеть только то, что ОС отдала процессу, нормально, что они не показывают никакого уменьшения использования памяти.
Кстати, помните, что если вы char ** array
содержите указатели на вещи, выделенные с помощью malloc
, вы должны сначала free
их , иначе у вас будет утечка памяти.
Второй вопрос:
Строки C заканчиваются нулем, т. е. последним символом строки всегда является \0
, обозначающий конец строки, а strlen
указывает длину строки без нулевого ограничителя. Таким образом, если вы не добавите этот +1
, вы выделяете на char
меньше памяти, чем требуется для фактического хранения вашей строки.
Приложение
Под не работает я подразумеваю, что произошел сбой (проблема могла быть где-то еще), но когда я изменил его на realloc (X, 0), он действительно работал в смысле удаления используемой динамической используемой памяти.
Как говорится на странице руководства,
Сбои в malloc(), calloc(), realloc() или free() почти всегда связаны с повреждением кучи, например, с переполнением выделенного фрагмента или двойным освобождением одного и того же указателя.
Вероятно, у вас есть какая-то другая ошибка в вашем коде, но, не видя ее, невозможно сказать, что и где идет не так.
person
Matteo Italia
schedule
26.05.2013
realloc(array, 0)
не эквивалентноfree(array)
. Эта идиома просто неверна. У меня нет времени, чтобы написать ответ в данный момент, но, надеюсь, кто-то может объяснить это хорошо. - person R.. GitHub STOP HELPING ICE   schedule 26.05.2013free
не работает? - person Theodoros Chatzigiannakis   schedule 26.05.2013free
состоит в том, чтобы делать память доступной для последующего выделения и не уменьшать значение счетчика свободного места, о котором сообщаетps
,memfree
или аналогичная системная утилита. - person Jens   schedule 26.05.2013free
, в вашем коде есть ошибка.realloc(X, 0)
может быть или не быть эквивалентнымfree(X)
. Это зависит от реализации. В вашей системе они явно не эквивалентны, потому чтоfree
дает сбой, аrealloc
нет. Отключив сбой, вы просто сделаете вид, что ошибки не существует. Тем не менее, он все еще там. Я бы рекомендовал попробовать найти. - person n. 1.8e9-where's-my-share m.   schedule 26.05.2013array = realloc(array, newSize);
плохо. Еслиrealloc
не удается, старая память не будетfree
d, а будет возвращенаNULL
, которая стирает старый указатель, оставляя вас с утечкой памяти. Правильноtmp = realloc(array, newSize); if (tmp == NULL) {Do something appropriate here, keeping in mind that array still points to the original block and is still valid.} else {array = tmp;}
. - person Joshua Green   schedule 27.05.2013