Skip to content

Commit f6366bc

Browse files
committed
feat(foundation): add safe_free, safe_str_free, safe_buf_free, safe_grow memory helpers
Four new inline helpers in platform.h alongside existing safe_realloc: - safe_free(ptr): frees and NULLs any pointer (prevents double-free) - safe_str_free(&str): frees const char* and NULLs (replaces free((void*)str)) - safe_buf_free(buf, &count): frees array and zeros its count - safe_grow(arr, n, cap, factor): one-line capacity-doubling realloc
1 parent ac8fde6 commit f6366bc

1 file changed

Lines changed: 42 additions & 0 deletions

File tree

src/foundation/platform.h

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,48 @@ static inline void *safe_realloc(void *ptr, size_t size) {
3131
return tmp;
3232
}
3333

34+
/* Safe free: frees and NULLs a pointer to prevent double-free / use-after-free.
35+
* Accepts void** so it works with any pointer type via the macro. */
36+
static inline void safe_free_impl(void **pp) {
37+
if (pp && *pp) {
38+
free(*pp);
39+
*pp = NULL;
40+
}
41+
}
42+
#define safe_free(ptr) safe_free_impl((void **)(void *)&(ptr))
43+
44+
/* Safe string free: frees a const char* and NULLs it.
45+
* Casts away const so callers don't need the (void*) dance. */
46+
static inline void safe_str_free(const char **sp) {
47+
if (sp && *sp) {
48+
free((void *)*sp);
49+
*sp = NULL;
50+
}
51+
}
52+
53+
/* Safe buffer free: frees a heap array and zeros its element count.
54+
* Use for dynamic arrays paired with a size_t count. */
55+
static inline void safe_buf_free_impl(void **buf, size_t *count) {
56+
if (buf && *buf) {
57+
free(*buf);
58+
*buf = NULL;
59+
}
60+
if (count) {
61+
*count = 0;
62+
}
63+
}
64+
#define safe_buf_free(buf, countp) safe_buf_free_impl((void **)(void *)&(buf), (countp))
65+
66+
/* Safe grow: doubles capacity and reallocs when count reaches cap.
67+
* Usage: safe_grow(arr, count, cap, growth_factor)
68+
* Evaluates to the new arr (NULL on OOM — old memory freed by safe_realloc). */
69+
#define safe_grow(arr, n, cap, factor) do { \
70+
if ((size_t)(n) >= (size_t)(cap)) { \
71+
(cap) *= (factor); \
72+
(arr) = safe_realloc((arr), (size_t)(cap) * sizeof(*(arr))); \
73+
} \
74+
} while (0)
75+
3476
/* ── Memory mapping ────────────────────────────────────────────── */
3577

3678
/* Map a file read-only into memory. Returns NULL on error.

0 commit comments

Comments
 (0)