Другие ответили, как работает malloc(0)
. Я отвечу на один из вопросов, которые вы задали, на которые еще не ответили (я думаю). Вопрос о realloc(malloc(0), 0)
:
Что такое malloc(0)
? Будет ли ответ таким же для realloc(malloc(0),0)
?
Стандарт говорит, что это о realloc(ptr, size)
:
- если
ptr
является NULL
, он ведет себя как malloc(size)
,
- иначе (
ptr
не NULL
), он освобождает старый указатель на объект, чтобы на ptr
и возвращает указатель на новый выделенный буфер. Но если size
равно 0, C89 говорит, что эффект эквивалентен free(ptr)
. Интересно, что я не могу найти это утверждение в проекте C99 (n1256 или n1336). В C89 единственным разумным значением для возврата в этом случае будет NULL
.
Итак, есть два случая:
malloc(0)
возвращает NULL
на реализацию. Затем ваш звонок realloc()
эквивалентен realloc(NULL, 0)
.Это эквивалентно malloc(0)
сверху (и это в этом случае NULL
).
malloc(0)
возвращает не NULL
. Затем звонок эквивалентен free(malloc(0))
. В этом случае malloc(0)
и realloc(malloc(0), 0)
составляют не эквивалент.
Обратите внимание, что есть интересный случай здесь: во втором случае, когда malloc(0)
возвращается Непро- NULL
на успех, он все еще может вернуться NULL
, чтобы указать отказ. Это приведет к вызову типа: realloc(NULL, 0)
, который будет эквивалентен malloc(0)
, который может возвращать или не возвращать NULL
.
Я не уверен, если это упущение в C99 является контроль или, если это означает, что в C99, realloc(ptr, 0)
для не NULL
ptr
не эквивалентно free(ptr)
. Я просто попробовал это с gcc -std=c99
, и выше это эквивалентно free(ptr)
.
Edit: Я думаю, я понимаю, что ваша путаница:
Давайте посмотрим на фрагмент из вашего примера кода:
ptr = malloc(0);
if (ptr == realloc(ptr, 1024))
выше, не такой же, как malloc(0) == realloc(malloc(0), 1024)
. Во втором случае вызов malloc()
выполняется дважды, тогда как в первом вы передаете ранее выделенный указатель на realloc()
.
Давайте сначала проанализируем первый код. Предполагая, что malloc(0)
не возвращает NULL
при успешном выполнении, ptr
имеет действующее значение. Когда вы делаете realloc(ptr, 1024)
, realloc()
в основном дает вам новый буфер размером 1024, а ptr
становится недействительным. Соответствующая реализация может вернуть тот же адрес, что и в ptr
. Таким образом, ваше условие if
может вернуть true. (Обратите внимание, однако, если посмотреть на ptr
после realloc(ptr, 1024)
, это может быть неопределенное поведение.)
Теперь задаваемый вопрос: malloc(0) == realloc(malloc(0), 1024)
. В этом случае предположим, что и malloc(0)
на LHS и RHS возвращают не NULL
. Тогда они гарантированно будут отличаться. Кроме того, возвращаемое значение от malloc()
на LHS еще не было free()
d, поэтому любые другие malloc()
, calloc()
или realloc()
могут не вернуть это значение. Это означает, что если вы написали свое состояние как:
if (malloc(0) == realloc(malloc(0), 1024)
puts("possible");
вы не увидите possible
на выходе (если оба malloc()
и realloc()
не удастся, и вернуть NULL
).
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
void *p1;
void *p2;
p1 = malloc(0);
p2 = realloc(p1, 1024);
if (p1 == p2)
puts("possible, OK");
/* Ignore the memory leaks */
if (malloc(0) == realloc(malloc(0), 1024))
puts("shouldn't happen, something is wrong");
return 0;
}
В OS X мой код ничего не выводил, когда я запускал его. В Linux он печатает possible, OK
.
@ tommieb75: это помогает ответить на исходный вопрос. Сказав это, этот вопрос состоит из двух частей, а вторая часть интереснее, а не обман. См. Мой ответ на этот вопрос. –