2017-02-17 11 views
4

Определена ли реализация поведения? Если NULL и размер == 0 передаются realloc():Что делать, если NULL и размер 0 переданы в realloc()?

int main(void) 
{ 
    int *ptr = NULL; 

    ptr = realloc(ptr, 0); 

    if(ptr == NULL) 
    { 
     printf("realloc fails.\n"); 
     goto Exit; 
    } 

    printf("Happy Scenario.\n"); 

Exit: 
    printf("Inside goto.\n"); 

return 0; 
} 

Приведенный выше код должен печатать «перераспределить сбой», не так ли? Но это не так? Я где-то читал, что этот вызов realloc может также вернуть NULL. Когда это происходит?

+0

Возможный дубликат [Realloc on NULL-значный (или неопределенный) указатель] (http://stackoverflow.com/questions/12134315/realloc-on-null-valued-or-undefined-pointer) –

+1

Возможный дубликат doesn 't адресует конкретную точку поведения 'void * vp = realloc (NULL, 0);'. –

+0

Я согласен с @Jonathan здесь. похоже, что упомянутый дубликат не обсуждает поведение realloc'ing для 0 элементов и информацию об указателе, который вы вернетесь. Старые платформы Microsoft имели проблемы при распределении для 0 элементов. – jww

ответ

7

Такое поведение определяется реализацией.

От C standard:

Раздел 7.22.3.5 (realloc):

Если ptr пустой указатель, функция realloc ведет себя как malloc функции для заданного размера. В противном случае, если ptr не совпадает с указателем ранее возвращенное управления памятью функции, или если пространство было высвобождены вызовом функцию free или realloc, поведение не определено. Если память для нового объекта не может быть выделена, старый объект не освобождается и его значение не изменяется.

Так realloc(NULL, 0) такая же, как malloc(0)

Если мы затем посмотрим на раздел 7.22.3.4 (malloc):

malloc функция выделяет пространство для объекта, размер которого определяется size и значение которого является неопределенным.

Функция malloc возвращает либо нулевой указатель, либо указатель на выделенное пространство.

Стандарт не устанавливает, что происходит, когда 0 передается в

Но если вы посмотрите на Linux man page:.

malloc() функция выделяет байт размера и возвращает указатель на выделенной памяти. Память не инициализируется. Если размер равен 0, , то malloc() возвращает либо NULL, либо уникальное значение указателя, которое затем может быть отправлено . free().

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

В отличие от этого, MSDN говорит:

Если размер 0, таНос выделяет элемент нулевой длины в куче и возвращает действительный указатель на этот элемент. Всегда проверяйте возврат от malloc, даже если объем запрошенной памяти невелик.

Для MSVC вы не получите указатель NULL.

+0

Спасибо! Это было полезно, особенно контраст с MSDN. – user7375520

11

перераспределить (3) док:

Если PTR является NULL, то вызов эквивалентен таНос (размер), для всех значений размера

таНос (3) документ:

Если размер равен 0, то malloc() возвращает либо NULL, либо уникальное значение указателя, которое впоследствии может быть успешно передано в free().

Да, это определенная реализация, вы либо получите нуль, либо указатель, который вы можете освободить.

+2

Если вы получаете ненулевой указатель, указатель, который вы получаете, должен быть освобожден, чтобы избежать утечек, но не может быть разыменован (поскольку он обеспечивает 0 байтов законно доступной памяти). –

+0

@JonathanLeffler «... указатель, который вы получаете, должен быть освобожден, чтобы избежать утечек» применяется ко всем указателям, выделенным 0 или ненулевыми размерами, которые не возвращают «NULL». В конце концов они должны быть свободными, чтобы избежать утечек. OTOH, если 'malloc (0)' возвращает non-'NULL', освобождение сразу же может уменьшить использование памяти и, может быть, хорошая идея, но это не проблема _leak_. – chux

6

Вызов

realloc(NULL, size); 

эквивалентно

malloc(size); 

И что malloc() делает, когда просят выделить 0 байт немного неясно, стандарт не говорит. Я думаю, что это определяется реализацией. Это в принципе «не имеет значения»; либо он возвращает NULL, либо возвращает указатель, где вы можете легально обращаться к нулевым байтам, которые в значительной степени похожи. Оба могут быть переданы в free().