C / CHAPTER 13
Resizing allocations without losing ownership
AdvancedPreserve the original allocation when growth fails.
By the end of this chapter
- Use a temporary realloc result
- Check multiplication before allocating
- Track logical length separately from capacity
The idea
A dynamic buffer needs both a logical length and allocated capacity. Growth may move the allocation, invalidating pointers into its old storage. For a nonzero requested size, realloc failure returns null while leaving the original allocation available. Assigning its result directly to the only owner pointer can therefore lose access to that original allocation.
Use a temporary pointer, check success, and update ownership only afterward. Check element-count multiplication against SIZE_MAX before computing allocation bytes. Avoid relying on the special and version-sensitive zero-size behavior of realloc; handle an empty-buffer policy explicitly. Newly added storage is not initialized, so write new elements before reading them. On every path, decide which pointer still owns the allocation and free exactly that allocation once.
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int *values = malloc(2 * sizeof *values);
if (!values) return 1;
values[0] = 3;
int *next = realloc(values, 4 * sizeof *values);
if (!next) { free(values); return 1; }
values = next;
values[2] = 8;
printf("%d %d\n", values[0], values[2]);
free(values);
}3 8 when allocation and growth succeed.
Growth preserves existing bytes, and the newly read element is explicitly initialized first.
Try it yourself
Write a grow helper that rejects zero or overflowing capacities and leaves the original buffer intact on allocation failure.
Use your own editor for this exercise. Runnable challenges on CodeQuest are available for JavaScript, Python, and SQL.
CHECK YOUR UNDERSTANDING