Как правильно использовать realloc (), когда он терпит неудачу и возвращает NULL? - PullRequest
16 голосов
/ 26 июля 2010

Может ли кто-нибудь обобщить, как правильно использовать realloc()?

Что вы делаете, когда realloc() не удается?

Из того, что я видел до сих пор, кажется, чтоrealloc() терпит неудачу, вы должны free() старый указатель.Это правда?

Вот пример:

   1.  char *ptr = malloc(sizeof(*ptr) * 50);
   2.  ...
   3.  char *new_ptr = realloc(ptr, sizeof(*new_ptr) * 60);
   4.  if (!new_ptr) {
   5.      free(ptr);
   6.      return NULL;
   7.  }

Предположим, что realloc() завершится неудачно в строке 3.Правильно ли я поступаю по линии 5 по free() ing ptr?

Ответы [ 4 ]

17 голосов
/ 26 июля 2010

С http://www.c -faq.com / malloc / realloc.html

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

Следовательно, вам действительно нужно будет освободить ранее выделенную память.

1 голос
/ 26 июля 2010

Это зависит от того, что вы хотите сделать. Когда realloc терпит неудачу, что вы хотите сделать: освободить старый блок или оставить его живым и неизменным? Если вы хотите освободить его, то освободите его.

Следует также помнить, что в C89 / 90, если вы делаете запрос realloc с нулевым целевым размером, функция realloc может возвращать нулевой указатель, даже если исходная память была успешно освобождена. Это было дефектом в C89 / 90, так как не было никакого способа определить успех от сбоя при нулевом возврате.

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

0 голосов
/ 26 июля 2010

Если происходит сбой realloc, я не думаю, что вы захотите удалить оригинальный блок, так как вы потеряете его.Похоже, что realloc изменит размер старого блока (или вернет указатель на новое местоположение) и в случае успеха вернет указатель на старый блок (или новое местоположение), а при ошибке вернет NULL.Если он не может выделить новый блок, старый блок остается без изменений.

0 голосов
/ 26 июля 2010

Редактировать: Исправление, некоторые люди осуждают меня за то, что я сказал, способ, которым вы выделили свой указатель, кажется лучшей практикой среди них, меня учили всегда идти с приведением типов в sizeof(), но, очевидно, ваш путь правильнее, так что не обращайте внимания на то, что я сказал =)

Взглянув на http://en.wikipedia.org/wiki/Malloc#realloc, прежде чем, возможно, вам что-то помогло.

Вы не совсем понимаете sizeof() - в нем есть значение размера аргумента, который вы ему передаете, в байтах. Например, sizeof(int) будет равно 4 в большинстве 32-битных систем, но вы все равно должны использовать sizeof(int) вместо 4, потому что компиляция вашего кода в 64-битной системе (как пример) сделает это значение равным 8 и Ваш код все равно будет хорошо скомпилирован. Для чего вы выделяете память? Указатели? Если это так, вы должны использовать sizeof(void*) вместо этого (вы можете сказать sizeof(int*), но общепринято не указывать компилятору, что вы хотите хранить в этих указателях, поскольку все указатели должны быть одинакового размера - так большинство программистов говорят sizeof(void*)), если вам нужно место для символов, используйте sizeof(char) и т. д.

Однако вы вправе сохранить возвращаемое значение realloc() в новом указателе и проверить его, хотя многие программисты считают, что в системе всегда достаточно памяти, и обходятся ею.

...