Использование realloc для сокращения выделенной памяти - PullRequest
26 голосов
/ 16 августа 2011

Простой вопрос о функции realloc в C: если я использую realloc для уменьшения блока памяти, на который указывает указатель, освобождается ли «лишняя» память?Или это нужно как-то вручную освободить?

Например, если я сделаю

int *myPointer = malloc(100*sizeof(int));
myPointer = realloc(myPointer,50*sizeof(int));
free(myPointer);

Будет ли у меня утечка памяти?

Ответы [ 4 ]

20 голосов
/ 16 августа 2011

Нет, у вас не будет утечки памяти. realloc просто пометит остальные «доступные» для будущих malloc операций.

Но вам все равно придется free myPointer позже. Кроме того, если вы используете 0 в качестве размера в realloc, это будет иметь тот же эффект, что и free в некоторых реализациях . Как сказали Стив Джессоп и Р. в комментариях, на это не стоит полагаться.

15 голосов
/ 16 августа 2011

Определенно нет утечки памяти, но при вызове realloc для уменьшения размера может произойти как минимум 3 вещи:

  1. Реализация разделяет выделенный блок памяти на новыйзапрашиваемая длина и освобождает неиспользованную часть в конце.
  2. Реализация делает новое распределение с новым размером, копирует старое содержимое в новое местоположение и освобождает все старое распределение.
  3. Реализация вообще ничего не делает.

Вариант 3 был бы довольно плохой реализацией, но совершенно законным;«утечки памяти» по-прежнему нет, потому что все это все равно будет освобождено, если вы позже вызовете free.

Что касается вариантов 1 и 2, то лучше будет зависеть от того, предпочитаете ли вы производительность илиизбегая фрагментации памяти.Я полагаю, что большинство реализаций реального мира склоняются к выполнению варианта 1.

4 голосов
/ 16 августа 2011

Новый код все еще пропускает исходное распределение, если происходит сбой realloc.Я ожидаю, что большинство реализаций никогда не прекратят сокращать блок, но это разрешено.Правильный способ вызова realloc, будь то увеличение или уменьшение блока, void * tmp = realloc (myPointer, 50 * sizeof (int));if (! tmp) {/ * как-то обрабатывает ошибку.myPointer по-прежнему указывает на старый блок, который все еще выделен * /} myPointer = tmp ;.- Стив Джессоп 48 минут назад

Эй, я не могу понять, как ответить на ваш комментарий, извините.

Нужно ли приводить tmp к типу myPointer?В этом случае мне нужно написать

myPointer = (int*)tmp

Кроме того, в этом случае, когда я освобождаю (myPointer) Память, на которую указывает tmp, также будет освобождена, верно?Так что не надо делать

free(myPointer)
free(tmp)
3 голосов
/ 16 августа 2011

В том смысле, как вы дали свой код, да, в нем может быть утечка.Идея realloc в том, что она может вернуть вам новое местоположение ваших данных.Как будто вы делаете это в своем вопросе, вы теряете тот указатель, который посылает вам realloc.

int *myPointer2 = realloc(myPointer,50*sizeof(int));
assert(myPointer2); 
myPointer = myPointer2;
...