What happens if malloc((size_t)NULL) in C [duplicate] - c

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.

Related

Can the memory allocation functions be inconsistent regarding zero size?

The C specification says this about the memory allocation functions:
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.
Do all the allocation functions have to be consistent in this regard? Can malloc(0) return a non-null pointer, while realloc(someptr, 0) returns a null pointer?
Can calloc(0, 0) be different from malloc(0)? It would have been simple for the calloc() specification to say that calloc(nmemb, size) is equivalent to malloc(nmemb * size) followed by zeroing the memory, but this equivalence is not explicit.

The initialization of the dynamically allocated memory in C [duplicate]

This question already has answers here:
Is malloc() initializing allocated array to zero?
(9 answers)
Closed 4 years ago.
I am still confused with the two functions malloc() and calloc()
As we know calloc() initialize the memory it allocates while malloc() doesn't.
But when I tried the following code, the result seemed unexpected.
typedef struct{
int *val;
}Node;
int main()
{
Node *q=(Node*)malloc(sizeof(Node));
if(q->val==NULL) printf("malloc initialized memory\n");
Node *p=(Node*)calloc(1,sizeof(Node));
if(p->val==NULL) printf("calloc initialized memory\n");
}
The variables 'val' of val of p and q are both NULL. Isn't q->val uninitialized?
Can anyone explain it to me? Thanks!
The malloc function does not initialize the memory it allocates. The contents will be indeterminate (and might seem "random" or "garbage").
If you want to zero-initialize the memory (which means that all pointers are NULL) then use calloc, or explicitly initialize the data.
Also note that in C you should not cast the return of malloc (and siblings).
When a variable is uninitialized, formally it means that its value is indeterminate. It could be any value, and 0 is just as random as any other value. Just because you read 0 doesn't necessarily mean the variable was initialized.
You're actually invoking undefined behavior by attempting to read q->val because 1) it was not initialized and 2) its address was never taken. Had its address been taken first you would not have undefined behavior unless the indeterminate value was a trap representation.
The memory chunk returned via malloc(), contains indeterminate value. Attempt to use that value may incur unspecified result, as nothing about the value can be guranteed.
Quoting C11, chapter 7.22.3.4/P2
The malloc function allocates space for an object whose size is specified by size and whose value is indeterminate.

Why does malloc work with zero size? [duplicate]

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).

Free memory in c without using free() function [duplicate]

This question already has answers here:
Freeing allocated memory: realloc() vs. free()
(7 answers)
Closed 9 years ago.
I have tried freeing memory without using free() as below
int *ptr = malloc(20);
realloc(ptr, 0);
Will it work?
C language standards differ on this one: in C90 passing zero size was the same as calling free:
If size is zero, the memory previously allocated at ptr is deallocated as if a call to free was made, and a null pointer is returned.
However, this changed in C99:
If size is zero, the return value depends on the particular library implementation: it may either be a null pointer or some other location that shall not be dereferenced.
Note that freeing is no longer a requirement; neither is returning a NULL when zero size is passed.
realloc(ptr, 0) is not equivalent to free(ptr)
The standard C11 says:
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.
Why because realloc does below things,
It creates new memory of size specified.
Copies contents from old memory to newer.
Frees the old memory
Returns address of new memory
Maybe, but you can't count on it. From the docs:
If new_size is zero, the behavior is implementation defined (null pointer may be returned, or some non-null pointer may be returned that may not be used to access storage).
At least for POSIX: realloc(p, 0) is not the same as free(p).
From the current POSIX documentation on realloc():
Previous versions explicitly permitted a call to realloc (p, 0) to free the space pointed to by p and return a null pointer. While this behavior could be interpreted as permitted by this version of the standard, the C language committee have indicated that this interpretation is incorrect.

What does malloc(0) return? [duplicate]

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).

Resources