pointers-memory · intermediate · ~22 min
Realloc + explicit zero-fill, with attention to OOM.
Resize a heap buffer with realloc, then zero only the newly added bytes. realloc leaves the extended region uninitialised — it may contain stale heap data — so zeroing just the new part is the safe building block.
Implement void *grow_zeroed(void *ptr, size_t old_size, size_t new_size) that calls realloc(ptr, new_size), zeroes the bytes from old_size up to new_size when growing, and returns the new pointer. No main — the grader calls it.
ptr — the existing block (may be NULL, in which case this acts like malloc). old_size — its current size in bytes. new_size — the desired size in bytes.
Returns the resized pointer, with bytes [old_size, new_size) set to 0 when growing. Returns NULL on allocation failure — in that case the original ptr is still valid and must NOT be freed.
char *p = malloc(4); memcpy(p, "abc", 4);
tmp = grow_zeroed(p, 4, 16) -> "abc\0" preserved, bytes 4..15 all zero
char *p = malloc(16); memset(p, 'X', 16);
tmp = grow_zeroed(p, 16, 8) -> shrunk; no zero-fill needed
ptr == NULL: behaves like malloc(new_size) then zeroes it.new_size <= old_size): no zero-fill.realloc into a temporary so an OOM doesn't lose (and leak) the original.For a nonzero request, store the result in a temporary and adopt it only after success. If it is NULL, keep and eventually free the original owner.
Transfer exercise: apply the lesson to a complete function contract.
ptr — the existing block (may be NULL, in which case this acts like malloc). old_size — its current size in bytes. new_size — the desired size in bytes.
Returns the resized pointer, with bytes [old_size, new_size) set to 0 when growing. Returns NULL on allocation failure — in that case the original ptr is still valid and must NOT be freed.
For new_size=0 explicitly free ptr and return NULL. Otherwise ptr owns old_size bytes (old_size=0 when ptr is NULL). Failure returns NULL leaving ptr valid. Success preserves old bytes and zeroes only the added region; caller adopts the result.
#include <stddef.h>
void *grow_zeroed(void *ptr, size_t old_size, size_t new_size) { /* TODO */ return NULL; }
Losing the old owner or zeroing preserved bytes; relying on realloc(p,0).
NULL/zero old allocation; shrink; equal sizes; grow; explicit zero new size; allocation failure.
Amortised O(new_size - old_size) for the zero-fill plus realloc cost.
Solve this exercise in the browser editor — compile and run against the test harness, no setup required.