From b6b7a01987dca604a161c8c73a240ec4430baed0 Mon Sep 17 00:00:00 2001 From: Mosder Date: Fri, 21 Aug 2026 11:50:51 +0200 Subject: refactor: renamed mem/alloc.h to safe.h and made it be a collection of "safe" wrappers for "unsafe" functions --- Makefile | 8 +++---- README.md | 4 ++-- include/moslib.h | 2 +- include/moslib/ds/array.h | 2 +- include/moslib/mem/alloc.h | 50 ----------------------------------------- include/moslib/safe.h | 37 ++++++++++++++++++++++++++++++ include/moslib/string.h | 2 +- src/ds/array.c | 2 +- src/mem/alloc.c | 45 ------------------------------------- src/safe.c | 42 ++++++++++++++++++++++++++++++++++ tests/mem/alloc_tests.c | 43 ----------------------------------- tests/mem/alloc_tests.h | 3 --- tests/safe_tests.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++ tests/safe_tests.h | 3 +++ tests/tests.c | 4 ++-- 15 files changed, 149 insertions(+), 154 deletions(-) delete mode 100644 include/moslib/mem/alloc.h create mode 100644 include/moslib/safe.h delete mode 100644 src/mem/alloc.c create mode 100644 src/safe.c delete mode 100644 tests/mem/alloc_tests.c delete mode 100644 tests/mem/alloc_tests.h create mode 100644 tests/safe_tests.c create mode 100644 tests/safe_tests.h diff --git a/Makefile b/Makefile index 0c4622b..6fc62cd 100644 --- a/Makefile +++ b/Makefile @@ -16,19 +16,17 @@ static: compile headers headers: sudo cp -r include/* /usr/local/include -compile: memory structures +compile: structures $(CC) $(CFLAGS) -c src/tester.c + $(CC) $(CFLAGS) -c src/safe.c $(CC) $(CFLAGS) -c src/string.c -memory: - $(CC) $(CFLAGS) -c src/mem/alloc.c - structures: $(CC) $(CFLAGS) -c src/ds/array.c $(CC) $(CFLAGS) -c src/ds/hashmap.c test: - $(CC) $(CFLAGS_TEST) -c tests/mem/alloc_tests.c + $(CC) $(CFLAGS_TEST) -c tests/safe_tests.c $(CC) $(CFLAGS_TEST) -c tests/ds/array_tests.c $(CC) $(CFLAGS_TEST) -c tests/string_tests.c $(CC) $(CFLAGS_TEST) -c tests/ds/hashmap_tests.c diff --git a/README.md b/README.md index 9c83639..660a8e7 100644 --- a/README.md +++ b/README.md @@ -4,11 +4,11 @@ Just a bunch of useful code for me put into a single lib, so I don't have to imp Defnitely not the best implementations ever made, but they're mine, so idc. ## Contains: -- memory management helpers +- "safe" wrappers for "unsafe" functions - testing framework - dynamic array implementation ## Planned: -- string slices +- length aware string slices - hashmap implementation - a bunch of other stuff most certainly diff --git a/include/moslib.h b/include/moslib.h index 777d951..fa549da 100644 --- a/include/moslib.h +++ b/include/moslib.h @@ -10,6 +10,6 @@ // This way you can, for example, avoid collisions #include "moslib/ds/array.h" -#include "moslib/mem/alloc.h" +#include "moslib/safe.h" #include "moslib/string.h" #include "moslib/tester.h" diff --git a/include/moslib/ds/array.h b/include/moslib/ds/array.h index 8f76901..b4c80f5 100644 --- a/include/moslib/ds/array.h +++ b/include/moslib/ds/array.h @@ -148,7 +148,7 @@ // ---------------------------------------------------------------------------------------------------- // ===================================== END OF QUICK USAGE GUIDE ===================================== -#include "moslib/mem/alloc.h" +#include "moslib/safe.h" #ifndef MOSLIB_DS_ARRAY_H #define MOSLIB_DS_ARRAY_H diff --git a/include/moslib/mem/alloc.h b/include/moslib/mem/alloc.h deleted file mode 100644 index 564c70f..0000000 --- a/include/moslib/mem/alloc.h +++ /dev/null @@ -1,50 +0,0 @@ -// moslib/mem/alloc.h -// Helper functions for general memory management - -#include - -#ifndef MOSLIB_MEM_ALLOC_H -#define MOSLIB_MEM_ALLOC_H - -// Attempt count for alloc functions -#ifndef MOS_MAX_ALLOC_ATTEMPTS -#define MOS_MAX_ALLOC_ATTEMPTS 3 -#endif // MOS_MAX_ALLOC_ATTEMPTS - -#ifndef MOS_FORCE_PREFIXES - -#define safe_malloc mos_safe_malloc -#define safe_realloc mos_safe_realloc - -#endif // MOS_FORCE_PREFIXES - -// Tries to malloc MOS_MAX_ALLOC_ATTEMPTS times -// If all attempts fail - exits with EXIT_FAILURE code -// -// Arguments: -// size -// count of bytes to malloc -// -// Returns: -// pointer to the allocated memory -#define mos_safe_malloc(size) mos_safe_malloc_fn(size, MOS_MAX_ALLOC_ATTEMPTS, __FILE__, __LINE__, __func__) - -// Tries to realloc MOS_MAX_ALLOC_ATTEMPTS times -// If all attempts fail - exits with EXIT_FAILURE code -// -// Arguments: -// ptr -// pointer to the memory to realloc -// -// size -// new desired count of bytes of memory -// -// Returns: -// pointer to the reallocated memory -#define mos_safe_realloc(ptr, size) mos_safe_realloc_fn(ptr, size, MOS_MAX_ALLOC_ATTEMPTS, __FILE__, __LINE__, __func__) - -// Function prototypes for macros -extern void *mos_safe_malloc_fn(size_t size, size_t att, const char *file, int line, const char *func); -extern void *mos_safe_realloc_fn(void *ptr, size_t size, size_t att, const char *file, int line, const char *func); - -#endif // MOSLIB_MEM_ALLOC_H diff --git a/include/moslib/safe.h b/include/moslib/safe.h new file mode 100644 index 0000000..8074c31 --- /dev/null +++ b/include/moslib/safe.h @@ -0,0 +1,37 @@ +// moslib/safe.h +// "Safe" wrappers for some "unsafe" functions +// aka "I don't want to check for NULL every single time" header + +#include + +#ifndef MOSLIB_SAFE_H +#define MOSLIB_SAFE_H + +#ifndef MOS_FORCE_PREFIXES + +#define safe_malloc mos_safe_malloc +#define safe_calloc mos_safe_calloc +#define safe_realloc mos_safe_realloc + +#endif // MOS_FORCE_PREFIXES + +typedef struct { + const char *file; + int line; + const char *func; +} MosSafeErrInfo; + +#define mos_err_info ((MosSafeErrInfo){.file = __FILE__, .line = __LINE__, .func = __func__}) + +// All of the below function-like macros do the same thing the original functions do +// They check whether the operation suceeded and if not - they exit with an error message +#define mos_safe_malloc(size) mos_safe_malloc_fn(size, mos_err_info) +#define mos_safe_calloc(count, size) mos_safe_calloc_fn(count, size, mos_err_info) +#define mos_safe_realloc(ptr, size) mos_safe_realloc_fn(ptr, size, mos_err_info) + +// Function prototypes for macros +extern void *mos_safe_malloc_fn(size_t size, MosSafeErrInfo info); +extern void *mos_safe_calloc_fn(size_t count, size_t size, MosSafeErrInfo info); +extern void *mos_safe_realloc_fn(void *ptr, size_t size, MosSafeErrInfo info); + +#endif // MOSLIB_SAFE_H diff --git a/include/moslib/string.h b/include/moslib/string.h index e01c975..bc9efff 100644 --- a/include/moslib/string.h +++ b/include/moslib/string.h @@ -549,4 +549,4 @@ extern MosStringSlice mos_ss_find_str(MosStringSlice ss, const char *target); // utf-8 length extern size_t mos_ss_utf8_len(MosStringSlice ss); -#endif // MOSLIB_MEM_ALLOC_H +#endif // MOSLIB_STRING_H diff --git a/src/ds/array.c b/src/ds/array.c index cdaf152..2b28a21 100644 --- a/src/ds/array.c +++ b/src/ds/array.c @@ -5,7 +5,7 @@ #include #include -#include "moslib/mem/alloc.h" +#include "moslib/safe.h" MosArrHeader *arr2hdr(void *arr) { return (MosArrHeader *)arr - 1; diff --git a/src/mem/alloc.c b/src/mem/alloc.c deleted file mode 100644 index 60da131..0000000 --- a/src/mem/alloc.c +++ /dev/null @@ -1,45 +0,0 @@ -#define MOS_FORCE_PREFIXES -#include "moslib/mem/alloc.h" - -#include -#include -#include - -#define ERR_MESS(fl, ln, fn, msg) "%s:%d - error in function %s:\n%s\n", fl, ln, fn, msg - -void *mos_safe_malloc_fn(size_t size, size_t att, const char *file, int line, const char *func) { - for (size_t i = 0; i < att; i++) { - void *p = malloc(size); - if (p) - return p; - if (i < att - 1) { - fprintf(stderr, ERR_MESS(file, line, func, "malloc failed - retrying in 1s...")); - sleep(1); - } - } - - char errmes[64]; - sprintf(errmes, "FATAL: malloc failed %zu times - exiting...", att); - fprintf(stderr, ERR_MESS(file, line, func, errmes)); - exit(EXIT_FAILURE); -} - -void *mos_safe_realloc_fn(void *ptr, size_t size, size_t att, const char *file, int line, const char *func) { - if (!ptr) - return mos_safe_malloc_fn(size, att, file, line, func); - - for (size_t i = 0; i < att; i++) { - void *p = realloc(ptr, size); - if (p) - return p; - if (i < att - 1) { - fprintf(stderr, ERR_MESS(file, line, func, "realloc failed - retrying in 1s...")); - sleep(1); - } - } - - char errmes[64]; - sprintf(errmes, "FATAL: realloc failed %zu times - exiting...", att); - fprintf(stderr, ERR_MESS(file, line, func, errmes)); - exit(EXIT_FAILURE); -} diff --git a/src/safe.c b/src/safe.c new file mode 100644 index 0000000..7c7627e --- /dev/null +++ b/src/safe.c @@ -0,0 +1,42 @@ +#define MOS_FORCE_PREFIXES +#include "moslib/safe.h" + +#include +#include +#include +#include + +#define ERR_MESS(msg, ...) err_mess(info, msg, __VA_ARGS__) + +void err_mess(MosSafeErrInfo info, const char *msg, ...) { + va_list args; + va_start(args, msg); + fprintf(stderr, "%s:%d - fatal error in function %s:\n", info.file, info.line, info.func); + vfprintf(stderr, msg, args); + fprintf(stderr, "\n"); + va_end(args); +} + +void *mos_safe_malloc_fn(size_t size, MosSafeErrInfo info) { + void *p = malloc(size); + if (p) + return p; + ERR_MESS("failed to malloc %zu bytes", size); + exit(EXIT_FAILURE); +} + +void *mos_safe_calloc_fn(size_t count, size_t size, MosSafeErrInfo info) { + void *p = calloc(count, size); + if (p) + return p; + ERR_MESS("failed to calloc %zu items of %zu size", count, size); + exit(EXIT_FAILURE); +} + +void *mos_safe_realloc_fn(void *ptr, size_t size, MosSafeErrInfo info) { + void *p = realloc(ptr, size); + if (p) + return p; + ERR_MESS("failed to realloc %p to %zu bytes", ptr, size); + exit(EXIT_FAILURE); +} diff --git a/tests/mem/alloc_tests.c b/tests/mem/alloc_tests.c deleted file mode 100644 index 5b71887..0000000 --- a/tests/mem/alloc_tests.c +++ /dev/null @@ -1,43 +0,0 @@ -#include "alloc_tests.h" -#define MOS_MAX_ALLOC_ATTEMPTS 1 -#include "moslib/mem/alloc.h" - -#include -#include - -Test malloc_exit() { - safe_malloc(ULLONG_MAX); -} - -Test test_safe_malloc() { - void *p = safe_malloc(1024); - test_assert(p != NULL, "Failed to malloc 1KiB"); - - suppress_output(&stderr); - test_assert_exit(malloc_exit, EXIT_FAILURE); - unsuppress_outputs(); -} - -Test realloc_exit() { - void *p = NULL; - safe_realloc(p, ULLONG_MAX); -} - -Test test_safe_realloc() { - void *p = NULL; - p = safe_realloc(p, 1024); - test_assert(p != NULL, "Failed to realloc NULL to 1KiB"); - - p = safe_realloc(p, 4096); - test_assert(p != NULL, "Failed to realloc 1KiB to 4KiB"); - - suppress_output(&stderr); - test_assert_exit(realloc_exit, EXIT_FAILURE); - unsuppress_outputs(); -} - -void mem_alloc_tests(Tester *tester) { - TestGroup *group = add_test_group(tester, "moslib/mem/alloc.h"); - add_test(group, test_safe_malloc); - add_test(group, test_safe_realloc); -} diff --git a/tests/mem/alloc_tests.h b/tests/mem/alloc_tests.h deleted file mode 100644 index aaf70a4..0000000 --- a/tests/mem/alloc_tests.h +++ /dev/null @@ -1,3 +0,0 @@ -#include - -extern void mem_alloc_tests(Tester *tester); diff --git a/tests/safe_tests.c b/tests/safe_tests.c new file mode 100644 index 0000000..1d48a48 --- /dev/null +++ b/tests/safe_tests.c @@ -0,0 +1,56 @@ +#include "safe_tests.h" +#include "moslib/safe.h" + +#include +#include + +Test malloc_exit() { + safe_malloc(ULLONG_MAX); +} + +Test test_safe_malloc() { + void *p = safe_malloc(1024); + test_assert(p != NULL, "Failed to malloc 1KiB"); + + suppress_output(stderr); + test_assert_exit(malloc_exit, EXIT_FAILURE); + unsuppress_outputs(); +} + +Test realloc_exit() { + void *p = NULL; + safe_realloc(p, ULLONG_MAX); +} + +Test calloc_exit() { + safe_calloc(ULLONG_MAX, ULLONG_MAX); +} + +Test test_safe_calloc() { + void *p = safe_calloc(16, 16); + test_assert(p != NULL, "Failed to calloc 16 items of 16 bytes"); + + suppress_output(stderr); + test_assert_exit(calloc_exit, EXIT_FAILURE); + unsuppress_outputs(); +} + +Test test_safe_realloc() { + void *p = NULL; + p = safe_realloc(p, 1024); + test_assert(p != NULL, "Failed to realloc NULL to 1KiB"); + + p = safe_realloc(p, 4096); + test_assert(p != NULL, "Failed to realloc 1KiB to 4KiB"); + + suppress_output(stderr); + test_assert_exit(realloc_exit, EXIT_FAILURE); + unsuppress_outputs(); +} + +void safe_tests(Tester *tester) { + TestGroup *group = add_test_group(tester, "moslib/safe.h"); + add_test(group, test_safe_malloc); + add_test(group, test_safe_calloc); + add_test(group, test_safe_realloc); +} diff --git a/tests/safe_tests.h b/tests/safe_tests.h new file mode 100644 index 0000000..8127b4c --- /dev/null +++ b/tests/safe_tests.h @@ -0,0 +1,3 @@ +#include + +extern void safe_tests(Tester *tester); diff --git a/tests/tests.c b/tests/tests.c index d7ce15b..648ab4c 100644 --- a/tests/tests.c +++ b/tests/tests.c @@ -2,13 +2,13 @@ #include "ds/array_tests.h" #include "ds/hashmap_tests.h" -#include "mem/alloc_tests.h" +#include "safe_tests.h" #include "string_tests.h" int main(void) { Tester *tester = new_tester(); - mem_alloc_tests(tester); + safe_tests(tester); ds_array_tests(tester); string_tests(tester); ds_hashmap_tests(tester); -- cgit v1.2.3