Question

Reading some literature, I was able to grasp that realloc takes in a void pointer and a size variable and re-allocates the memory of the block the void pointer points to.

  • What will happen if realloc is called on an integer pointer (int *) with a size of character? And vice versa.

  • What can be a possible application of this? (An example would definitely help.)

Was it helpful?

Solution

The realloc() function is the all-in-one memory management system.

  • If called with a null pointer and a non-zero size, it allocates memory.
  • If called with a valid pointer and a zero size, it frees memory.
  • If called with a valid pointer and a non-zero size, it changes the size of the allocated memory.

If you call realloc() with an invalid pointer — one which was not obtained from malloc(), calloc() or realloc() — then you get undefined behaviour.

You could pass realloc() an integer pointer to an allocated space of sizeof(char) bytes (1 byte), but you'd be in danger of invoking undefined behaviour. The problem is not with realloc(); it is with the code that was given an unusable integer pointer. Since only 1 byte was allocated but sizeof(int) is greater than 1 (on essentially all systems; there could be exceptions, but not for someone asking this question), there is no safe way to use that pointer except by passing it to free() or realloc().

Given:

int *pointer = malloc(sizeof(char));

you cannot do *pointer = 0; because there isn't enough space allocated (formally) for it to write to. You cannot do int x = *pointer; because there isn't enough space allocated (formally) for it to read from. The word 'formally' is there because in practice, the memory allocators allocate a minimum size chunk, which is often 8 or 16 bytes, so there actually is space after the one byte. However, your are stepping outside the bounds of what the standard guarantees, and it is possible to conceive of memory allocators that would hand you exactly one byte. So, don't risk it. An integer pointer to a single byte of allocated memory is unusable except as an argument to the memory allocation functions.

The first argument to realloc() is a void *. Since you're going to have a prototype in scope (#include <stdlib.h>), the compiler will convert the int * to a void * (if there's anything to do for such a cast), and as long as the space pointed at was allocated, everything will be fine; realloc() will change the allocation size, possibly returning the same pointer or possibly returning a different pointer, or it will release the space if the new size is zero bytes.

OTHER TIPS

There is a vitally important requirement to non-NULL pointers that you pass to realloc: they must themselves come from a call to malloc, calloc or realloc, otherwise the behavior is undefined.

If you allocate a chunk of memory sufficient to store an int and then realloc for a char, you will always get back the same pointer, because sizeof(char) is less than or equal to the sizeof(int):

int* intPtr = malloc(sizeof(int));
int* otherPtr = realloc(intPtr, sizeof(char));
// intPtr == otherPtr

If you try it the other way around, you will almost certainly get back the same pointer as well, because memory allocators rarely, if ever, parcel the memory to chunks smaller than sizeof(int). However, the result is implementation-dependent, so theoretically you may get back a different address.

As far as the utility of any of the above exercises goes, it is not useful: realloc has been designed with the intention to help you manage variable-sized arrays, simplifying the code for growing the size of such arrays, and potentially reducing the number of allocations and copying. I do not see a reason for realloc-ing a scalar.

The type of the first parameter of realloc is void *, as you said yourself. So the function argument that you pass is converted to a void pointer, which is an implicit and safe conversion.

It's the same as if you called a function with a long int parameter with an int argument, essentially.

Realloc takes the size in bytes. If you do

int* a= malloc(sizeof(int));

and then

a=realloc(a,1);

of course a will now not be big enough for an int type and writing an int in it will give you odd behavior.

As stated by dasblinkenlight, realloc doesn't make sense for a scalar. In your example:

int * a = malloc(sizeof(int));
int * b = realloc(a,sizeof(char));

Would result in a == b, simply because sizeof(char) < sizeof(int) and there is no reason for moving the data to a new location.
The difference is, that after the realloc you are writing your int to unallocated space, as you decreased the allocated space using realloc. Here this is only of theoretical relevance. Because of alignment it is very unlikely, that the os is reusing the freed memory. But you shouldn't rely on that. This is undefined behavior.
It could become relevant, if you resize the space of a long int to an int. This depends on your architecture.
Writing to unallocated space is like laying a time bomb and not knowing when it will explode. You should only read from / write to allocated space.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top