Skip to content

Reallocate memory

The advantage of dynamic memory allocation is that you can change your allocations. If you asked for an array of two values, you may later want to be able to expand that array to three or four elements. Alternatively, an array with twenty elements may have some data removed and be shrunk down to only 5 elements. All of this is possible with dynamic memory allocation. You can ask to have the memory you were allocated changed to a different size.

Figure x.y: You can change the size of the allocation, growing or shrinking the number of element

You can change the size of the allocation, growing or shrinking the number of element

Realloc - Why, When, and How

You can use realloc when you have an existing heap allocation that you want to change. You may need more space, or have reduced the size you need. In either case the realloc call can let you change the allocation.

In C/C++

Like malloc and calloc, realloc allows you to allocate space from the heap. Using realloc you can change (reallocate) space on the heap, by passing in the existing pointer and the new size.

FunctionArgumentsReturnsDescription
reallocthe pointer to reallocate, and new size in bytes.a pointer (void *) to the new addressChanges the memory allocation and returns a pointer to it.

As with the other memory allocation functions, you need to import the stdlib.h header file. The realloc function has the following prototype:

void *realloc( void *ptr, size_t size )

To use this safely you need to think about how it works:

  • If it can reallocate at the same location, it will and returns the original pointer.
  • If needed to move the allocation, it will do and returns the new address of the data.
  • When you are out of memory, or it cannot find a new place to store the data, it will return nullptr / NULL.

To handle all three of these cases you need to make sure you do not update the original pointer value until you have checked if the realloc worked. If you get back NULL, then you need to have kept the original pointer so that you can get back to the space on the heap, and potentially free it as you are out of space in memory.

Example

The following example shows how to use realloc to both allocation and then change the memory allocation. This would work equally well if you used malloc or calloc to do the original memory allocation.

#include <stdlib.h>
int main()
{
int *p = NULL;
// get space for one integer from the heap - same as malloc
p = (int *)realloc(p, sizeof(int));
*p = 1; // give it a value...
// reallocate space for 5 integers
int *new_p;
new_p = (int *)realloc(p, sizeof(int) * 5);
if ( new_p != NULL )
{
p = new_p;
}
// p[0] is still 1...
// but there is now also space for p[1]...p[4]
// free all space allocated
free(p);
p = NULL;
return 0;
}
Example calls to realloc

Notice how we use an if statement to check if the realloc worked. If it did, we update the pointer, otherwise it retains its original value.

To make this work in reality we would need to put this in a struct where we also keep track of the size of the array as we have before.


Realloc (allocation at original address)

Navigate the slide-show below to understand how realloc works when the memory reallocation happens to expand at the original memory address


The program begins by declaring an int pointer p and initializing it to NULL
We then call realloc to allocate memory for an integer on the heap, and assign the address of that area to our int pointer variable p. NOTE: That realloc() doesn't initialize the memory space with 0. It will retain whatever value was already existing in this space.
At line 7, we assign the value 1 to our integer space on the heap
Now we declare another int pointer variable, new_p. In the next step (at line 9) we'll want to grow the memory area currently pointed to by p by calling realloc again. new_p will be the pointer to this new reallocation of our memory area currently being pointed to by p.
At line 9, we call realloc again to grow the memory area pointed to by p from 1 integer to 5 integers. When it can, realloc will grow the memory area using the same original location. You can see here, there is no allocated memory blocking expansion, and so our memory can simply grow at that the same memory address that was used originally. The original memory address that was originally allocated to p (0x1A2) has therefore been returned and assigned to new_p which represents the start of our new expanded memory. Again, note that any uninitialized elements in the the expanded memory area are not initialized to 0 by realloc
At line 10 we test to make sure that new_p is not NULL which would mean that our memory reallocation had failed. Since new_p contains a valid address, our realloc from the previous step was successful
Because we can't be sure if our realloc reallocates memory at our original location, if we would like to continue working with our original pointer variable p, we need to re-assign p the value of our updated memory location. So at this step, we assign p the value of new_p (even though it is redundant in this case, we can never be sure whether the original location or a new location was returned)
Now let's try assigning a new value (the int value 9) to the 4th element of our memory region (which contains an array of ints)
Next, we'll execute a for loop to print out the values of our array
Line 18 calls the <strong>free</strong> function, passing it the pointer p. This will free the space allocated on the heap for the memory area that was allocated to the pointer p. p then becomes a dangling pointer (as does new_p)
p is then assigned the null pointer value (nullptr), cutting it's ties to the heap space that was allocated previously. new_p however, still remains a dangling pointer
Finally, the program returns 0 and ends

Realloc (allocation at new address)

Navigate the slide-show below to understand how realloc works when the memory reallocation happens to shift from it’s original memory space to a new area


Before beginning, we note that there is an area on the heap where some memory has already been allocated by the system (this will become relevant later on). The program begins by declaring an int pointer p and initializing it to NULL
We then call realloc to allocate memory for an integer on the heap, and assign the address of that area (0x1A2) to our int pointer variable p. NOTE: That realloc() doesn't initialize the memory space with 0. It will retain whatever value was already existing in this space. Also note that the system allocated space for our integer on the heap just before the memory that was already in use by the system
At line 7, we assign the value 1 to our integer space on the heap
Now we declare another int pointer variable, new_p. In the next step (at line 9) we'll want to grow the memory area currently pointed to by p by calling realloc again. new_p will be the pointer to this new reallocation of our memory area currently being pointed to by p.
At line 9, we call realloc again to grow the memory area pointed to by p from 1 integer to 5 integers. When it can, realloc will grow the memory area using the same original location, but if it can't it will allocate a new space in memory. You can see that in this case, a new memory space has been allocated at 0xCD8 because the next available space to our current memory at 0x1A2 was already occupied. Any values from the original memory area are also copied over to this new reallocated memory region. new_p is assigned the address of this new memory region and the old memory region is de-allocated. Again, note that any uninitialized elements in the the expanded memory area are not initialized to 0 by realloc
At line 10 we test to make sure that new_p is not NULL which would mean that our memory reallocation had failed. Since new_p contains a valid address, our realloc from the previous step was successful
Because we can't be sure if our realloc reallocates memory at our original location, if we would like to continue working with our original pointer variable p, we need to re-assign p the value of our updated memory location. So at this step, we assign p the value of new_p, hence making sure it points to the correct memory region
Now let's try assigning a new value (the int value 9) to the 4th element of our memory region (which contains an array of ints)
Next, we'll execute a for loop to print out the values of our array
Line 18 calls the <strong>free</strong> function, passing it the pointer p. This will free the space allocated on the heap for the memory area that was allocated to the pointer p. p then becomes a dangling pointer (as does new_p)
p is then assigned the null pointer value (nullptr), cutting it's ties to the heap space that was allocated previously. new_p however, still remains a dangling pointer
Finally, the program returns 0 and ends. Note that the system memory that was allocated to the heap prior to our program running still remains allocated at this point, since it must be being used by some other process

Reallocating multidimensional arrays

If you need to change the allocation of a multidimensional array, the implications will depend on how this is implemented. If you have a ragged array, then you can reallocate each of the points, giving you the ability to resize different parts of the array as you go. With a rectangular array, you can resize associated memory and then move values from their old positions to their new positions. When you do this, you need to make sure you do this from the end of the old array back to the start.