This question already has an answer here:
- what's the point in malloc(0)? 16 answers
What does malloc(0)
returns? Would the answer be same for realloc(malloc(0),0)
?
#include<stdio.h>
#include<malloc.h>
int main()
{
printf("%p\n", malloc(0));
printf("%p\n", realloc(malloc(0), 0));
return 0;
}
Output from linux gcc:
manav@manav-workstation:~$ gcc -Wall mal.c
manav@manav-workstation:~$ ./a.out
0x9363008
(nil)
manav@manav-workstation:~$
The output keep changing everytime for malloc(0)
. Is this a standard answer? And why would anyone be interested in getting such a pointer, other than academic research?
EDIT:
If malloc(0)
returns dummy pointer, then how does following works:
int main()
{
void *ptr = malloc(0);
printf("%p\n", realloc(ptr, 1024));
return 0;
}
EDIT:
The following code outputs "possible" for every iteration. Why should it not fail ?
#include<stdio.h>
#include<malloc.h>
int main()
{
int i;
void *ptr;
printf("Testing using BRUTE FORCE\n");
for (i=0; i<65000; i++)
{
ptr = malloc(0);
if (ptr == realloc(ptr, 1024))
printf("Iteration %d: possible\n", i);
else
{
printf("Failed for iteration %d\n", i);
break;
}
}
return 0;
}
Others have answered how
malloc(0)
works. I will answer one of the questions that you asked that hasn't been answered yet (I think). The question is aboutrealloc(malloc(0), 0)
:The standard says this about
realloc(ptr, size)
:ptr
isNULL
, it behaves likemalloc(size)
,ptr
is notNULL
), it deallocates the old object pointer to byptr
and returns a pointer to a new allocated buffer. But ifsize
is 0, C89 says that the effect is equivalent tofree(ptr)
. Interestingly, I can't find that statement in C99 draft (n1256 or n1336). In C89, the only sensible value to return in that case would beNULL
.So, there are two cases:
malloc(0)
returnsNULL
on an implementation. Then yourrealloc()
call is equivalent torealloc(NULL, 0)
. That is equivalent tomalloc(0)
from above (and that isNULL
in this case).malloc(0)
returns non-NULL
. Then, the call is equivalent tofree(malloc(0))
. In this case,malloc(0)
andrealloc(malloc(0), 0)
are not equivalent.Note that there is an interesting case here: in the second case, when
malloc(0)
returns non-NULL
on success, it may still returnNULL
to indicate failure. This will result in a call like:realloc(NULL, 0)
, which would be equivalent tomalloc(0)
, which may or may not returnNULL
.I am not sure if the omission in C99 is an oversight or if it means that in C99,
realloc(ptr, 0)
for non-NULL
ptr
is not equivalent tofree(ptr)
. I just tried this withgcc -std=c99
, and the above is equivalent tofree(ptr)
.Edit: I think I understand what your confusion is:
Let's look at a snippet from your example code:
The above is not the same as
malloc(0) == realloc(malloc(0), 1024)
. In the second, themalloc()
call is made twice, whereas in the first, you're passing a previously allocated pointer torealloc()
.Let's analyze the first code first. Assuming
malloc(0)
doesn't returnNULL
on success,ptr
has a valid value. When you dorealloc(ptr, 1024)
,realloc()
basically gives you a new buffer that has the size 1024, and theptr
becomes invalid. A conforming implementation may return the same address as the one already inptr
. So, yourif
condition may return true. (Note, however, looking at the value ofptr
afterrealloc(ptr, 1024)
may be undefined behavior.)Now the question you ask:
malloc(0) == realloc(malloc(0), 1024)
. In this case, let's assume that both themalloc(0)
on the LHS and RHS returns non-NULL
. Then, they are guaranteed to be different. Also, the return value frommalloc()
on the LHS hasn't beenfree()
d yet, so any othermalloc()
,calloc()
, orrealloc()
may not return that value. This means that if you wrote your condition as:you won't see
possible
on the output (unless bothmalloc()
andrealloc()
fail and returnNULL
).On OS X, my code didn't output anything when I ran it. On Linux, it prints
possible, OK
.The comp.lang.c FAQ has the following to say:
So, it's probably best to avoid using
malloc(0)
.In C89, malloc(0) is implementation dependent - I don't know if C99 has fixed this or not. In C++, using:
is well defined - you get a valid, non-null pointer. Of course, you can't use the pointer to access what it points to without invoking undefined behaviour.
As to why this exists, it is convenient for some algorithms, and means you don't need to litter your code with tests for zero values.