Why does this code not work?
char *x=malloc(100);
x++;
x=realloc(x, 200);
I mean x is a valid string pointer, just incremented by one?
See C Standard (C99, 7.20.3.4p3) on realloc and my emphasis:
void *realloc(void *ptr, size_t size);
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 the
calloc, malloc, or realloc function, or if the space has been deallocated by a call
to the free or realloc function, the behavior is undefined.
In your case x was returned by malloc, not x + 1. So your program invokes undefined behavior.
Think about what realloc does. How can it free the pointer at address x+1 when malloc actually created a pointer at address x?
In more concrete terms, let's assume you allocated 100 bytes at address 0x1000. Now x is incremented, pointing at 0x1001. Then you call realloc at the new address. Because none of malloc, calloc, and realloc created 0x1001, free (or equivalent code) used by the call to realloc has no idea how to do anything with 0x1001; it can't even fathom how many bytes of memory it occupies. It only knows about the 100 bytes at 0x1000.
The basic idea behind implementations of malloc and friends is that you keep track of the pointers assigned and how many bytes were allocated. Then when free is called later, the pointer passed to free is looked up. If there is no reference to that pointer passed to free, what else is there to do except crash? That, to me, is more logical than supposing you can keep using a pointer that may or may not be valid.
char *x=malloc(100);
x++;
x=realloc(x, 200);
In the code shown above the address pointed by the pointer x is changed before invoking the realloc() function. This is undefined behavior in C.
This is an undefined behavior as you if you think that you have obtained a pointer from malloc() which is wrong.
Clearly x was returned by malloc and its value was changed before calling realloc() Hence it is showing the undefined behavior.
Related
Normally, realloc() is used to reallocate a previously allocated pointer:
int *DynamicArray = malloc(sizeof(int)*SomeArbitraryValue);
// Some rando code where DynamicArray is used
DynamicArray = realloc(DynamicArray, sizeof(int)*SomeOtherArbitraryValue)
But can realloc() be used to directly allocate memory? As in
int *DynamicArray = realloc(/*...*/);
Can realloc() handle non-preallocated pointers?
Yes, just pass NULL to it's first argument.
The manpage of realloc(3) says ...
The realloc() function changes the size of the memory block pointed to by ptr to size bytes. The contents will be unchanged in the range from the start of the region up to the minimum of the old and new sizes. If the new size is larger than the old size, the added memory will not be initialized. 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). 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.
As the answer by #ZhangBoyang tells you, yes, assuming one possible interpretation of your question. However the way you've worded your question ("non-preallocated pointers") suggests you may have misunderstanding of some of the concepts involved. malloc does not "allocate pointers". It allocates objects, and pointers are values that point to objects. The lifetime of those objects are not connected to the lifetime of any particular pointer pointing to them.
Passing a pointer to realloc doesn't "do anything to" the pointer. It does something to the object pointed to by it. If the pointer is uninitialized or invalid, the call has undefined behavior and bad things will happen. If the pointer is a null pointer, however, realloc(ptr, n) will behave exactly as malloc(n).
I read about dynamic memory allocation in C using this reference.
That document Say's :
realloc() should only be used for dynamically allocated memory. If the
memory is not dynamically allocated, then behavior is undefined.
If we use realloc() something like this:
int main()
{
int *ptr;
int *ptr_new = (int *)realloc(ptr, sizeof(int));
return 0;
}
According to that reference, this program is undefined because pointer ptr not allocated dynamically.
But, If I use something like:
int main()
{
int *ptr = NULL;
int *ptr_new = (int *)realloc(ptr, sizeof(int));
return 0;
}
Is it also undefined behavior according to that reference?
I thing second case does not invoked undefined behaviour. Am I right?
The first case has undefined behavior, and the second doesn't. In the first case, the value of ptr is indeterminate. So passing that value to realloc or any function, is undefined by itself.
On the other hand, since realloc has well defined behavior when passed a null pointer value (it's just like calling malloc)1, the second piece of code is perfectly legitimate (other than the fact you don't free anything).
1 7.22.3.5 The realloc function / p3
If ptr is a null pointer, the realloc function behaves like the malloc function for the specified size.
In the first case the program almost sure will finish by segmentation fault as the linked lists that are created in the heap to find segments are not coherent, in the second case you call the realloc with the NULL first parameter, which means, is a call equivalent to malloc(size)
man realloc says:
void *malloc(size_t size);
void *realloc(void *ptr, size_t size);
If ptr is NULL, then the call is equivalent to malloc(size), for all values of size
The only authorative reference is the standard document. n1570 (the latest C11 standard) has the following to say:
§7.22.3.5 The realloc function, p3:
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. [...]
So, your second example is well-defined.
The first case is obviously undefined behavior because we don't know where the ptr is pointing or what the ptr is holding at that time. And c standard says that 7.20.3.4.2 The realloc function
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.
So first case is Undefined behavior.
In second case compiler knows what ptr has so it is valid but realloc()
will act as malloc() according to 7.20.3.4.3 The realloc function
If ptr is a null pointer, the realloc function behaves like the
malloc function for the specified size.
Is there a difference between those two variants of calling free after allocating memory on the heap:
// variant 1
int* p1 = (int*) malloc(sizeof(int)*4);
free(p1);
//variant 2
int* p2 = (int*) malloc(sizeof(int)*4);
free(*p2);
*p2 = NULL;
Yes, there is a difference.
Variant 2 is invalid. free expects a pointer previously returned by malloc, calloc, or realloc. *p2 is the first int in the allocated space, though. As man free says, undefined behavior occurs therefore (quotation adjusted for this specific case):
free() function frees the memory space pointed to by [p1], which must have been returned by a previous call to malloc(), calloc(), or realloc(). Otherwise, [...] undefined behavior occurs.
Notes:
don't cast the result of malloc
Yes. free(*p2) is invalid.
free frees the memory at the address it's given. Consider: what does p1 evaluate to? Its value is the pointer that malloc returned - so p1 evaluates to the pointer to the memory that malloc allocated.
What does *p2 evaluate to? Its value is the integer that is stored at the address of p2. This can be anything and it is very unlikely it'll be a valid pointer. Thus free will attempt to free an invalid memory address and you'll get a segfault if you're lucky.
Yes, there's a difference. The first way, called on a pointer pointing to memory allocated by malloc is right. The second, calling a dereference of such a pointer, attempts to free some arbitrary memory address (with the value held in the value that pointer is pointing to), and is just wrong.
free(p1);
This is valid as you allocate memory to p1 and then free, thus no problem.
free(*p2);
It is unlikely to be valid as *p2 may or may not be a valid pointer (which need to have an allocated memoty ).
using free() on a pointer which is not allcocated memory using malloc or similar will cause error.
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.
i just experiment the things on the c language
could you answer my question regarding the program i've written
void main()
{
char *p,; // created a pointer pointing to string
p = (char *) malloc(50); // dynamically create 50 bytes.
strcpy(p, "this code is written about the dynamic allocation");
p += 20;
free(p);
}
Now could anyone tell me what is the effect of free(p) statement will the last 30 bytes will be freed of and used for the future memory allocation.? what would be the output?
You are not supposed to free any addresses but those returned by malloc(), calloc() or realloc(). And p + 20 is no such address.
http://codepad.org/FMr3dvnq shows you that such a free() is likely to fail.
The free() function frees the memory space pointed to by ptr, which must have been returned by a previous call to malloc(), calloc() or realloc(). Otherwise, or if free(ptr) has already been called before, undefined behavior occurs. If ptr is NULL, no operation is performed.
Does the pointer passed to free() have to point to beginning of the memory block, or can it point to the interior? is also worth reading.
Even if you could use free() on any pointer that points to a malloc'd memory - your could would free it twice since you are calling free() on more than one memory inside that area. And double-frees are evil as they can result in security holes.
It will result in Undefined Behavior.
The free() function shall cause the space pointed to by ptr to be deallocated; that is, made available for further allocation. If ptr is a null pointer, no action shall occur. Otherwise, if the argument does not match a pointer earlier returned by the calloc(), malloc(), posix_memalign(), realloc(), strdup() function, or if the space has been deallocated by a call to free() or realloc(), the behavior is undefined.