What if NULL and size 0 are passed to realloc()? - c

Is the behavior implementation defined? If NULL and size == 0 are passed to realloc():
int main(void)
{
int *ptr = NULL;
ptr = realloc(ptr, 0);
if(ptr == NULL)
{
printf("realloc fails.\n");
goto Exit;
}
printf("Happy Scenario.\n");
Exit:
printf("Inside goto.\n");
return 0;
}
The above code should print "realloc fails", right? But it is not? I've read somewhere that this call to realloc may return NULL also. When does that happen?

This behavior is implementation defined.
From the C standard:
Section 7.22.3.5 (realloc):
3 If ptr is a null pointer, the realloc function behaves like the malloc function for the specified size. Otherwise, if ptr
does not match a pointer earlier returned by a memory management
function, or if the space has been deallocated by a call to
the free or realloc function, the behavior is undefined. If
memory for the new object cannot be allocated, the old object is
not deallocated and its value is unchanged.
So realloc(NULL, 0) is the same as malloc(0)
If we then look at section 7.22.3.4 (malloc):
2 The malloc function allocates space for an object whose size is specified by size and whose value is indeterminate.
3 The malloc function returns either a null pointer or a pointer to the allocated space.
The standard does not state what happens when 0 is passed in.
But if you look at the Linux man page:
The malloc() function allocates size bytes and returns a pointer to
the allocated memory. The memory is not initialized. If size is 0,
then malloc() returns either NULL, or a unique pointer value that can
later be successfully passed to free().
It explicitly states that the returned value can be freed but is not necessarily NULL.
In contrast, MSDN says:
If size is 0, malloc allocates a zero-length item in the heap and
returns a valid pointer to that item. Always check the return from
malloc, even if the amount of memory requested is small.
So for MSVC, you won't get a NULL pointer.

realloc(3) doc:
If ptr is NULL, then the call is equivalent to malloc(size), for all values of size
malloc(3) doc:
If size is 0, then malloc() returns either NULL, or a unique pointer value that can later be success‐fully passed to free().
So yes, it is implementation defined, you'll either get null or a pointer you can free.

The call
realloc(NULL, size);
is equivalent to
malloc(size);
And what malloc() does when asked to allocate 0 bytes is a bit unclear, the standard doesn't say. I think it's implementation-defined. It basically "doesn't matter"; either it returns NULL, or it returns a pointer where you can legally access zero bytes, those are pretty much alike. Both can be passed to free().

Related

Memory leak with malloc and fgetc

I'm having some trouble reading a like from user using malloc and getchar. I get the result, however, I get memory leaks using valgrind. I am pretty clueless in this and have asked my classmates and mentors, but none seem to find out why.
char *ReadLineFile(FILE *infile){
int i=0;
char c;
char *newStringLine;
newStringLine = (char *) malloc(sizeof(char));
while( (c = fgetc(infile)) != '\n' ){
newStringLine[i++] = c;
realloc(newStringLine, (sizeof(char) * (i+1)));
}
newStringLine[i] = '\0';
return newStringLine;
}
Valgrind gives me several errors, including Invalid write/read of 1, and invalid realloc.
Your usage of realloc() is erroneous.
realloc(), if successful, frees the passed pointer and returns a new pointer with the allocated memory. You need to
catch the return value of realloc() in a temporary pointer,
check against NULL to ensure success and then
If returned pointer is not NULL, i.e., reallocation is successful, use the new pointer.
If the returned pointer is NULL, make some decisions and you can keep using the old pointer (passed as argument).
Related, quoting C11, chapter §7.22.3.5
The realloc function deallocates the old object pointed to by ptr and returns a
pointer to a new object that has the size specified by size. [....]
and,
[...] If memory for the new object cannot be
allocated, the old object is not deallocated and its value is unchanged.
Otherwise, in case, realloc() is successful, you are (most probably) trying to use an already free-d memory, which , of course, causes undefined behavior.
Uh-oh, and did I mention, please see this discussion on why not to cast the return value of malloc() and family in C?

Freeing allocated memory: realloc() vs. free()

so I have a piece of memory allocated with malloc() and changed later with realloc().
At some point in my code I want to empty it, by this I mean essentially give it memory of 0. Something which would intuitively be done with realloc(pointer,0). I have read on here that this is implementation defined and should not be used.
Should I instead use free(), and then do another malloc()?
It depends on what you mean: if you want to empty the memory used, but still have access to that memory, then you use memset(pointer, 0, mem_size);, to re-initialize the said memory to zeroes.
If you no longer need that memory, then you simply call free(pointer);, which'll free the memory, so it can be used elsewhere.
Using realloc(pointer, 0) may work like free on your system, but this is not standard behaviour. realloc(ptr, 0) is not specified by the C99 or C11 standards to be the equivalent of free(ptr).
realloc(pointer, 0) is not equivalent to free(pointer).
The standard (C99, §7.22.3.5):
The realloc function
Synopsis
1
#include <stdlib.h>
void *realloc(void *ptr, size_t size);
Description
2 The realloc function deallocates the old object pointed to by ptr and returns a
pointer to a new object that has the size specified by size. The contents of the new
object shall be the same as that of the old object prior to deallocation, up to the lesser of
the new and old sizes. Any bytes in the new object beyond the size of the old object have
indeterminate values.
3 If ptr is a null pointer, the realloc function behaves like the malloc function for the
specified size. Otherwise, if ptr does not match a pointer earlier returned by a memory
management function, or if the space has been deallocated by a call to the free or
realloc function, the behavior is undefined. If memory for the new object cannot be
allocated, the old object is not deallocated and its value is unchanged.
Returns
4
The realloc function returns a pointer to the new object (which may have the same
value as a pointer to the old object), or a null pointer if the new object could not be
allocated.
As you can see, it doesn't specify a special case for realloc calls where the size is 0. Instead, it only states that a NULL pointer is returned on failure to allocate memory, and a pointer in all other cases. A pointer that points to 0 bytes would, then, be a viable option.
To quote a related question:
More intuitively, realloc is "conceptually equivalent" to to malloc+memcpy+free on the other pointer, and malloc-ing a 0-byte chunk of memory returns either NULL either a unique pointer, not to be used for storing anything (you asked for 0 bytes), but still to be freeed. So, no, don't use realloc like that, it may work on some implementations (namely, Linux) but it's certainly not guaranteed.
As another answer on that linked question states, the behaviour of realloc(ptr, 0) is explicitly defined as implementation defined according to the current C11 standard:
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
realloc() is used to increase or decrease the memory and not to free the memory.
Check this, and use free() to release the memory (link).
I don't think you mean "empty"; that would mean "set it to some particular value that I consider to be empty" (often all bits zero). You mean free, or de-allocate.
The manual page says:
If ptr is NULL, then the call is equivalent to malloc(size), for all values of size; if size is equal to zero, and ptr is not NULL, then the call is equivalent to free(ptr).
Traditionally you could use realloc(ptr, 0); as a synonym for free(ptr);, just as you can use realloc(NULL, size); as a synonym for malloc(size);. I wouldn't recommend it though, it's a bit confusing and not the way people expect it to be used.
However, nowadays in modern C the definition has changed: now realloc(ptr, 0); will free the old memory, but it's not well-defined what will be done next: it's implementation-defined.
So: don't do this: use free() to de-allocate memory, and let realloc() be used only for changing the size to something non-zero.
Use free() to free, to release dynamically allocated memory.
Although former documentations state that realloc(p, 0) is equivalent to free(p), the lastest POSIX documentation explictly states that this is not the case:
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.
And more over:
Applications should assume that if realloc() returns a null pointer, the space pointed to by p has not been freed.
Use free(pointer); pointer = 0 instead of realloc(pointer, 0).
void* realloc (void* ptr, size_t size);
In C90 :
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.
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.
I would use realloc to give a pointer more or less memory, but not to empty it. To empty the pointer I would use free.

Is the pointer calloc function return a pointer vector? (C language)

I'm trying to understand a c code, (SimpleScalar, bpred.c), there is the thing that confuses me a lot:
int *shiftregs;
shiftregs = calloc(1, sizeof(int));
int l1index, l2index;
l1index = 0;
l2index = shiftregs[l1index];
I delete some code that might not help. After the calloc call, *shiftregs becomes a pointer array? And what is the value of l2index? Thanks a lot!
Since shiftregs is a pointer to an int, *shiftregs is an int.
Since calloc guarantees that the memory it allocates is set to 0, and you've allocated enough memory to refer to shiftregs[0], l2index will be 0 (assuming calloc didn't fail and return NULL).
The calloc() function is being used to allocate a dynamic array of zeroed integers that can be referenced via the pointer shiftregs.
The value in l2index is going to be zero unless the allocation failed (calloc() returned NULL). If the allocation failed, you invoke undefined behaviour; anything could happen, but your program will probably crash. Check the allocation so that it doesn't crash!
l2index is 0. calloc set memory to zero. Following is Linux Programmer's Manual:
calloc() allocates memory for an array of nmemb elements of size
bytes each and returns a pointer to the allocated memory. The memory
is set to zero. If nmemb or size is 0, then calloc() returns
either NULL, or a unique pointer value that can later be successfully
passed to free().
Check if the calloc() return NULL.
If so, the "l2index = shiftregs[l1index];"will crash, for you try to get value from a NULL point(shiftregs).
If not, as they said l2index will be 0.

c realloc of memory from 0

is it possible to realloc memory from a pointer to NULL in C?
int *v = 0;
for(i = 0; i < 10; i++)
v = (int *) realloc(v, (i+1)*sizeof(int));
If ptr is NULL, then the call is equivalent to malloc(size), for all values of size.
Source: man 3 realloc
"In case that ptr is NULL, the function behaves exactly as malloc, assigning a new block of size bytes and returning a pointer to the beginning of it."
http://www.cplusplus.com/reference/clibrary/cstdlib/realloc/
By the way, I know this code is only for the question but you should always check the return value of realloc before updating your pointer:
int *p,*tmp;
tmp = (int *)realloc(p, nBytes);
if(tmp){
p = tmp;
}
else{
//Out of memory!
}
If you don't, you will lose your reference to your allocated memory when realloc fails.
From the Standard
7.20.3.4/3 ... If ptr is a null pointer, the realloc function behaves like the malloc function for the specified size.
From the manpage:
If ptr is NULL, the call is equivalent
to malloc(size); if size is equal to
zero, the call is equivalent to
free(ptr). Unless ptr is NULL, it must
have been returned by an earlier call
to malloc(), calloc() or realloc().
However, you shouldn't forget that realloc() can return NULL if it can't resize the memory. The code you posted could result in more than one block of memory being allocated if this happens, because the NULL return value will be fed back into realloc() which will then allocate a new block. (Hopefully you aren't really using that code anyway...)
yes.
from here
If ptr is a null pointer, realloc()
behaves like malloc() for the
specified size.
From realloc man page:
realloc() changes the size of the memory block pointed to by ptr to size bytes. The contents will be unchanged to the minimum of the old and new sizes; newly allocated memory will be uninitialized. If ptr is NULL, the call is equivalent to malloc(size); if size is equal to zero, the call is equivalent to free(ptr). Unless ptr is NULL, it must have been returned by an earlier call to malloc(), calloc() or realloc(). If the area pointed to was moved, a free(ptr) is done.

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