pointers-memory · intermediate · ~25 min
Realloc + explicit zero-fill, with attention to OOM.
Implement void *grow_zeroed(void *ptr, size_t old_size, size_t new_size).
Behaviour:
realloc(ptr, new_size).old_size, zero the bytes from old_size to new_size.ptr is still live; you must NOT free it).char *p = malloc(4); memcpy(p, "abc", 4); // 'a','b','c','\0'
p = grow_zeroed(p, 4, 16);
// First 4 bytes still "abc\0", bytes 4..15 are zero.
char *p = malloc(16); memset(p, 'X', 16);
p = grow_zeroed(p, 16, 8);
// Shrunk; no zero-fill needed (no bytes are "new").
A naïve realloc returns memory whose newly-extended region may contain previously-freed heap data. If you treat the whole buffer as initialised, you risk leaking arbitrary heap content into your output (logs, network responses, files).
realloc enlarges a buffer but leaves the new region uninitialised — that's a subtle source of information leaks (a CVE in OpenSSL leaked private-key bytes this way). Wrapping realloc with explicit zeroing of just the new region is the safer building block.
Pointer + old size + new size.
New pointer or NULL.
Use realloc + memset. Don't double-free on OOM.
#include <stddef.h>
void *grow_zeroed(void *ptr, size_t old_size, size_t new_size) { /* TODO */ return NULL; }
Doing ptr = realloc(ptr, new_size) — if realloc returns NULL, the original is lost (leak). Use a temporary. Zeroing the whole buffer (defeats the purpose of realloc when shrinking).
new_size == 0 (call free or realloc-to-0, depending on impl); shrink (no zero-fill); grow (zero only the new region); ptr == NULL (acts like malloc).
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.