mirror of
https://github.com/DeusData/codebase-memory-mcp.git
synced 2026-11-11 09:25:35 +08:00
feat(platform): add safe_free / safe_str_free / safe_buf_free / safe_grow
Centralize repetitive heap-management patterns into four wrappers alongside the existing safe_realloc: - safe_free(ptr): frees and NULLs a pointer to prevent double-free / use-after-free - safe_str_free(&str): frees a const char * and NULLs it without forcing the caller to cast away const at every site - safe_buf_free(buf, &count): frees a heap array and zeros the paired count, so the dangling-array / nonzero-count footgun cannot survive - safe_grow(arr, n, cap, factor): one-line capacity-doubling realloc for arrays whose elements do not own additional heap memory; documents the safe_realloc free-on-failure semantic so arrays of owned pointers keep using a manual realloc+cleanup pattern Cherry-picked from #209's platform.h additions; the rest of #209 duplicated work that landed via #206 and #207, so closing that PR in favor of this targeted commit. Co-authored-by: map588 <map588@pitt.edu>
This commit is contained in:
@@ -31,6 +31,52 @@ static inline void *safe_realloc(void *ptr, size_t size) {
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/* Safe free: frees and NULLs a pointer to prevent double-free / use-after-free.
|
||||
* Use via the safe_free() macro so the caller's pointer is actually cleared. */
|
||||
static inline void safe_free_impl(void **pp) {
|
||||
if (pp && *pp) {
|
||||
free(*pp);
|
||||
*pp = NULL;
|
||||
}
|
||||
}
|
||||
#define safe_free(ptr) safe_free_impl((void **)(void *)&(ptr))
|
||||
|
||||
/* Safe const string free: frees a const char* and NULLs it.
|
||||
* Casts away const so callers don't repeat the (void *) dance. */
|
||||
static inline void safe_str_free(const char **sp) {
|
||||
if (sp && *sp) {
|
||||
free((void *)*sp);
|
||||
*sp = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Safe buffer free: frees a heap array and zeros its element count.
|
||||
* Use for dynamic arrays paired with a size_t count. */
|
||||
static inline void safe_buf_free_impl(void **buf, size_t *count) {
|
||||
if (buf && *buf) {
|
||||
free(*buf);
|
||||
*buf = NULL;
|
||||
}
|
||||
if (count) {
|
||||
*count = 0;
|
||||
}
|
||||
}
|
||||
#define safe_buf_free(buf, countp) safe_buf_free_impl((void **)(void *)&(buf), (countp))
|
||||
|
||||
/* Safe grow: doubles capacity and reallocs when count reaches cap.
|
||||
* Note: uses safe_realloc which frees the old buffer on failure, so this is
|
||||
* only appropriate for arrays whose elements don't own additional heap memory.
|
||||
* For arrays of heap-allocated pointers, prefer a manual realloc+cleanup pattern.
|
||||
* Usage: safe_grow(arr, count, cap, growth_factor)
|
||||
* After the call, arr is the new buffer (NULL on OOM). */
|
||||
#define safe_grow(arr, n, cap, factor) \
|
||||
do { \
|
||||
if ((size_t)(n) >= (size_t)(cap)) { \
|
||||
(cap) *= (factor); \
|
||||
(arr) = safe_realloc((arr), (size_t)(cap) * sizeof(*(arr))); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/* ── Memory mapping ────────────────────────────────────────────── */
|
||||
|
||||
/* Map a file read-only into memory. Returns NULL on error.
|
||||
|
||||
Reference in New Issue
Block a user