This question already has answers here:
behaviour of malloc(0)
(3 answers)
Closed 5 years ago.
What happen I write malloc((size_t)NULL) for dynamic memory allocation in C?
int main()
{
char *ptr = malloc((size_t)NULL);
}
Is it allocate memory in heap section? or Is it undefined behavior?
What happen I write malloc(NULL)..
Wait, stop, you do not write malloc(NULL), why would you?
The argument to malloc() is the "size" of the memory expected, that is not supposed to be a null pointer constant.
Quoting C11, chapter §7.22.3.4, (emphasis mine)
void *malloc(size_t size);
The malloc function allocates space for an object whose size is specified by size and
whose value is indeterminate.
That said, for most cases, NULL is represented by integer constant value 0, so malloc(NULL) is equivalent to malloc(0), which again is implementation defined behavior.
Quoting chapter §7.22.3./P1
[...] 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.
This allocates the amount of memory defined by the constant NULL. If NULL == 0, then behavior is implementation defined.
This question already has answers here:
Undefined, unspecified and implementation-defined behavior
(9 answers)
What does malloc(0) return? [duplicate]
(9 answers)
Closed 6 years ago.
I am trying to understand inners of double pointer (which is pointer holding another pointer) to form an array of pointers. So, I am trying to run the following code by experimenting on malloc to debugging and see how it works. I am unable to understand what malloc(0) does in my case, but my code works by outputting "Hello World".
What is the diff between
pToCharsPointers = (char**) malloc(0);
and
pToCharsPointers = (char**) malloc(2 * sizeof(char*));
Please someone clarify what it is doing in my case.
#include <stdio.h>
char **pToCharsPointers;
int main(void)
{
pToCharsPointers = (char**) malloc(0);
char* pToChars = "Hello";
*pToCharsPointers = pToChars;
*(pToCharsPointers + 1)= "World";
printf("%s %s\n", *(pToCharsPointers + 0), *(pToCharsPointers + 1));
return 0;
}
Also, I would really appreciate if you anyone could explain how double pointers works with an example in memory for visualizing as I fail to see myself even though I tried to read about this in many places.
EDIT: Thanks everyone for sharing your answers, and it really helped to understand. I got a valid pointer with malloc(0) when I printed it, and can dereference it also without issues during multiple tries. Wanted to understand why its working. Seems like in my case undefined behavior was actually a expected one.
In your code
(char**) malloc(0);
is wrong for two reasons, like
Passing size as 0 is implementation defined behaviour and the returned pointer cannot be dereferenced. Quoting the manual page,
If size is 0, then malloc() returns either NULL, or a unique pointer value that can later be successfully passed to free().
Please see this discussion on why not to cast the return value of malloc() and family in C..
Any code, attempting to use the returned pointer for a code like yours, will be essentially dereferencing invalid memory which invokes undefined behavior. So, the output/behaviour of your program can neither be predicted nor reasonified.
OTOH, a statement like
pToCharsPointers = malloc(2 * sizeof(char*));
is valid but you ought to check the validity of the returned pointer to ensure malloc() is success.
I will try to explain:
pToCharsPointers = (char**) malloc(0);
this line will bring to pToCharPointers a pointer that you can't use
but you can't know if an error will come. don't do that!
char* pToChars = "Hello";
*pToCharsPointers = pToChars;
this line will bring *pToCharsPointers to pToChar that pointing to the "Hello".
*(pToCharsPointers + 1)= "World";
this line will write in *(pToCharsPointers + 1), that you can't know to where it is pointing, "World". also, an option to an error but not for sure.
printf("%s %s\n", *(pToCharsPointers + 0), *(pToCharsPointers + 1));
this line will print "Hello Wolrd" if you didn't get any errors yet.
It simply asks to allocate zero bytes. It is up to the implementation of malloc if it should return a null pointer or not.
Even if it returns a non-null pointer, you can't dereference it since it will automatically be out of bounds. Dereferencing the returned pointer will lead to undefined behavior in both cases.
When you do malloc(2 * sizeof(char*)) you allocate enough space for two pointers to char.
You forgot to include <stdlib.h>. Calling malloc() without a proper definition has undefined behavior. Explicitly casting its return value hides the fact that the compiler may assume it returns an int value. This cast is necessary in C++, where calling a function without a prior definition is invalid, but it is counter-productive in C.
Regarding your question: allocating a block of size zero can have two possible outcomes, depending on the implementation of your C library:
malloc(0) can return NULL, and attempting to store values at this address has undefined behavior.
malloc(0) can return a valid non-null pointer, but this pointer cannot be dereferenced, nor used to store anything as the size of the object it points to is 0.
In both cases, your code has undefined behavior, which may or may not be a crash.
This question already has answers here:
No out of bounds error
(7 answers)
Closed 6 years ago.
I am really confused about the following:
char *list = malloc(sizeof(char));
list[0] = 'a';
list[1] = 'b';
printf("%s\n", list);
My expectation was some kind of undefined behavior, because list has only memory for 1 char "object".
But the actual output is ab. Why can I access list[1] when list only has allocated memory for one char?
As per your memory allocation of sizeof(char) bytes (and considering the allocation is success),
list[1] = 'b';
is out-of-bound access, which invokes undefined behavior. There can be no expectation from a program causing UB. It can do anything, absolutely anything.
That said,
sizeof(char) is defined (guranteed) to be 1 in C standard.
Check for the success of malloc() before using the return value. Otherwise, the first access, list[0] itself will invoke UB as you'll end up dereferencing an invalid pointer (i.e., accessing invalid memory)
Passing a pointer to a non-null-terminated char array as argument to %s also invokes UB.
This question already has answers here:
behaviour of malloc(0)
(3 answers)
Why does strcpy "work" when writing to malloc'ed memory that is not large enough? [duplicate]
(5 answers)
Closed 7 years ago.
This is my code
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char* p;
p = (char*)malloc(0);
scanf("%s", p);
printf("%s", p);
free(p);
}
Could someone explain to me why every word i am typing via terminal is printed out to the user? I have malloc(0). Isn't supposed when i try to scanf to give me a segmentation fault?
Edit
Why this gives me a compilation error:
p = malloc(sizeof(char) * 2)
when i try to to avoid (void*)
error: cannot initialize a variable of type 'char *' with an rvalue of type 'void *'
The C Standard for malloc explicitly specifies this:
If the size of the space requested is 0, the behavior is
implementation-defined: the value returned shall be either a null
pointer or a unique pointer.
And for the return value from malloc:
If size is 0, either a null pointer or a unique pointer that can be
successfully passed to free() shall be returned. Otherwise, it shall
return a null pointer and set errno to indicate the error.
In regards to segmentation fault from the call to scanf, that is purely on the basis of the implementation and runtime behaviour of the environment, just down to luck rather than anything, the next time it is run, it may crash with segmentation fault.
The C standard 9899:2011 7.22.3 states that:
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.
Meaning that what is returned from malloc is implementation-defined behavior. You'll have to read your specific compiler documentation to see what it does in your case: return a null pointer or a non-zero pointer pointing at 0 bytes of data (likely a random garbage location).
In either case, the returned pointer is not pointing at a valid memory location. So if you attempt to write to it, you'll invoke undefined behavior. Meaning anything can happen: the program can crash & burn, or it can seem to work correctly and crash one month later, or anything else.
Why this gives me a compilation error: p = malloc(sizeof(char) * 2)
Because you are trying to compile C code with a C++ compiler. Don't do that. Some C++ compilers have an option you can set to compile with a C compiler instead.
Side note about an inconsistency in the C standard:
The standard Annex J actually list the above as unspecified behavior. I suspect this must be an error in Annex J, as the normative text cited above clearly states that this is implementation-defined. 7.22.3 is normative and Annex J is informative, so I would just ignore Annex J.
From opengroup -
If the size of the space requested is 0, the behavior is implementation-defined: the value returned shall be either a null pointer or a unique pointer.
Nothing is allocated by malloc(0). So , when you try to take input using scanf you invoke undefined behaviour .
Isn't supposed when i try to scanf to give me a segmentation fault?
No , it's not necessary when you have UB . Maybe you are not that lucky to get segmentation fault and got desired output( which may confuse).
This question already has answers here:
What's the point of malloc(0)?
(17 answers)
Closed 8 years ago.
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 for realloc(malloc(0),0)?
The standard says this about realloc(ptr, size):
if ptr is NULL, it behaves like malloc(size),
otherwise (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.
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.
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.
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.
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).
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 by ptr to size 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. If ptr is NULL, realloc()
behaves like malloc() for the specified size. If size is 0
and ptr 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).
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()).
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.
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).