问题
This question already has an answer here:
- what's the point in malloc(0)? 17 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;
}
回答1:
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)
:
- if
ptr
isNULL
, it behaves likemalloc(size)
, - otherwise (
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 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
.
回答2:
malloc(0)
is Implementation Defined as far as C99 is concerned.
From C99 [Section 7.20.3]
The order and contiguity of storage allocated by successive calls to the calloc, malloc, and realloc functions is unspecified. The pointer returned if the allocation succeeds is suitably aligned so that it may be assigned to a pointer to any type of object and then used to access such an object or an array of such objects in the space allocated (until the space is explicitly deallocated). The lifetime of an allocated object extends from the allocation until the deallocation. Each such allocation shall yield a pointer to an object disjoint from any other object. The pointer returned points to the start (lowest byte address) of the allocated space. If the space cannot be allocated, a null pointer is returned. If the size of the space requested is zero, the behavior is implementation- defined: either a null pointer is returned, or the behavior is as if the size were some nonzero value, except that the returned pointer shall not be used to access an object.
回答3:
In C89, malloc(0) is implementation dependent - I don't know if C99 has fixed this or not. In C++, using:
char * p = new char[0];
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.
回答4:
C99 standard
If the space cannot be allocated, a nullpointer is returned. If the size of the space requested is zero, the behavior is implementation-defined: either a null pointer is returned, or the behavior is as if the size were some nonzero value, except that the returned pointer shall not be used to access an object.
回答5:
The comp.lang.c FAQ has the following to say:
The ANSI/ISO Standard says that it may do either; the behavior is implementation-defined (see question 11.33). Portable code must either take care not to call malloc(0), or be prepared for the possibility of a null return.
So, it's probably best to avoid using malloc(0)
.
回答6:
See C99, section 7.20.3:
If the size of the space requested is zero, the behavior is implementationdefined: either a null pointer is returned, or the behavior is as if the size were some nonzero value, except that the returned pointer shall not be used to access an object.
This is valid for all three allocation functions (ie calloc()
, malloc()
and realloc()
).
回答7:
One point nobody cared to talk about yet, in your first program is that realloc
with length 0 is the same thing as free
.
from the Solaris man page:
The
realloc()
function changes the size of the block pointed to byptr
tosize
bytes and returns a pointer to the (possibly moved) block. The contents will be unchanged up to the lesser of the new and old sizes. Ifptr
isNULL
,realloc()
behaves likemalloc()
for the specified size. Ifsize
is0
andptr
is not a null pointer, the space pointed to is made available for further allocation by the application, though not returned to the system. Memory is returned to the system only upon termination of the application.
If one doesn't know that it can be a source of bad surprise (happened to me).
回答8:
I think it depends. I checked the Visual Studio 2005 sources and saw this in the _heap_alloc function:
if (size == 0)
size = 1;
I think that in many cases you may want a valid pointer, even when asking for zero bytes. This is because this consistent behavior makes it easier to check your pointers because: if you have a non-NULL pointer it's OK; if you have a NULL pointer you probably have a problem. That's why I think that most implementations will return a valid pointer, even when asking for zero bytes.
回答9:
If malloc(0) returns dummy pointer, then how does following works:
void *ptr = malloc(0);
printf("%p\n", realloc(ptr, 1024));
I don't know what you mean by "dummy pointer". If malloc(0)
returns non-NULL, then ptr
is a valid pointer to a memory block of size zero. The malloc
implementation saves this information in an implementation-specific way. realloc
knows the (implementation-specific) way to figure out that ptr
points to a memory block of size zero.
(How malloc
/realloc
/free
do this is implementation-specific. One possibility is to allocate 4 bytes more than requested and store the size just before the memory block. In that case, ((int *)ptr)[-1]
would give the memory block size, which is 0
. You should never do this from your code, it's only for use by realloc
and free
).
来源:https://stackoverflow.com/questions/2132273/what-does-malloc0-return