realloc()
realloc() lets you resize a block of memory that was previously obtained from malloc(), calloc(), or an earlier realloc() call. This is essential for building data structures like dynamic arrays, where you do not know the final size up front and need to grow the allocation as more data arrives.void *realloc(void *ptr, size_t new_size);
new_size bytes, with the contents of the original block preserved (up to the smaller of the old and new sizes). If it fails, it returns NULL and the original block is left completely untouched.The Critical Gotcha: The Address May Change
realloc() does not necessarily resize memory in place. If there is not enough contiguous free space right after the existing block, it will allocate a brand-new block elsewhere, copy your data over, and free the old block — all internally. The pointer it returns can therefore be a completely different address from the one you passed in.// WRONG: if realloc() fails, it returns NULL, and this line // overwrites 'ptr' with NULL -- losing your only reference to the // original block. That block is now leaked forever; you cannot free it. ptr = realloc(ptr, new_size);
realloc() fails, this statement assigns NULL straight into ptr, destroying the only pointer you had to the still-valid original block. You have now both failed to grow the memory and leaked the original allocation, with no way to free it.NULL, and only then update your real pointer:// CORRECT: use a temporary variable
int *temp = realloc(ptr, new_size);
if (temp == NULL) {
// realloc() failed -- 'ptr' is still valid and still points
// to the original, unmodified block. Handle the error here,
// e.g. by freeing 'ptr' and returning an error code.
fprintf(stderr, "realloc failed\n");
// ptr is still safe to use or free
} else {
// Success -- it is now safe to overwrite ptr
ptr = temp;
}Growing a Dynamic Array: A Worked Example
realloc() as more elements are added:#include <stdio.h>
#include <stdlib.h>
int main(void) {
int capacity = 2;
int count = 0;
int *arr = malloc(capacity * sizeof(int));
if (arr == NULL) {
fprintf(stderr, "Initial allocation failed\n");
return 1;
}
for (int i = 0; i < 6; i++) {
if (count == capacity) {
int new_capacity = capacity * 2; // double the capacity
int *temp = realloc(arr, new_capacity * sizeof(int));
if (temp == NULL) {
fprintf(stderr, "realloc failed\n");
free(arr); // arr is still valid -- clean it up
return 1;
}
arr = temp;
capacity = new_capacity;
}
arr[count] = i * i;
count++;
}
for (int i = 0; i < count; i++) {
printf("%d\n", arr[i]);
}
free(arr);
return 0;
}0 1 4 9 16 25
Correct vs Incorrect Pattern, Side by Side
Incorrect | Correct |
|---|---|
|
|
On failure: original block leaked, | On failure: |
Other realloc() Behaviors Worth Knowing
Calling
realloc(ptr, 0)has historically been used to free the block, but its behavior is subtle and implementation-defined in newer standards -- prefer callingfree()explicitly insteadCalling
realloc(NULL, size)behaves exactly likemalloc(size)-- useful if you want one code path that handles both the first allocation and later growthShrinking with realloc (
new_sizesmaller than the current size) is allowed and typically succeeds, preserving the retained portion of the data
realloc(ptr, new_size)resizes a block previously obtained from malloc/calloc/reallocIt may return a different address than the one you passed in -- never assume the block stayed in place
Always assign its result to a temporary pointer and check for
NULLbefore overwriting your original pointerOn failure, the original block is untouched and still must eventually be freed