What does malloc(0)
return?
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 about realloc(malloc(0), 0)
:
What does
malloc(0)
return? Would the answer be same forrealloc(malloc(0),0)
?
The standard says this about realloc(ptr, size)
:
ptr
is NULL
, it behaves like malloc(size)
,ptr
is not NULL
), it deallocates the old object pointer to by ptr
and returns a pointer to a new allocated buffer. But if size
is 0, C89 says that the effect is equivalent to free(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 be NULL
.So, there are two cases:
malloc(0)
returns NULL
on an implementation. Then your realloc()
call is equivalent to realloc(NULL, 0)
. That is equivalent to malloc(0)
from above (and that is NULL
in this case).malloc(0)
returns non-NULL
. Then, the call is equivalent to free(malloc(0))
. In this case, malloc(0)
and realloc(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 return NULL
to indicate failure. This will result in a call like: realloc(NULL, 0)
, which would be equivalent to malloc(0)
, which may or may not return NULL
.
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 to free(ptr)
. I just tried this with gcc -std=c99
, and the above is equivalent to free(ptr)
.
Edit: I think I understand what your confusion is:
Let's look at a snippet from your example code:
ptr = malloc(0);
if (ptr == realloc(ptr, 1024))
The above is not the same as malloc(0) == realloc(malloc(0), 1024)
. In the second, the malloc()
call is made twice, whereas in the first, you're passing a previously allocated pointer to realloc()
.
Let's analyze the first code first. Assuming malloc(0)
doesn't return NULL
on success, ptr
has a valid value. When you do realloc(ptr, 1024)
, realloc()
basically gives you a new buffer that has the size 1024, and the ptr
becomes invalid. A conforming implementation may return the same address as the one already in ptr
. So, your if
condition may return true. (Note, however, looking at the value of ptr
after realloc(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 the malloc(0)
on the LHS and RHS returns non-NULL
. Then, they are guaranteed to be different. Also, the return value from malloc()
on the LHS hasn't been free()
d yet, so any other malloc()
, calloc()
, or realloc()
may not return that value. This means that if you wrote your condition as:
if (malloc(0) == realloc(malloc(0), 1024)
puts("possible");
you won't see possible
on the output (unless both malloc()
and realloc()
fail and return 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;
}
On OS X, my code didn't output anything when I ran it. On Linux, it prints possible, OK
.