diff --git a/CMakeLists.txt b/CMakeLists.txt index 990ce53..8251c7a 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -27,10 +27,10 @@ else () set(DBG_FLAGS /fsanitize=address) endif () -add_executable(libguf_example src/test/example.c src/test/impls/str_impl.c src/test/impls/dict_impl.c src/test/impls/linalg_impl.c) +add_executable(libguf_example src/test/example.c src/test/impls/str_impl.c src/test/impls/dict_impl.c src/test/impls/linalg_impl.c src/test/impls/alloc_tracker_impl.c) target_include_directories(libguf_example PRIVATE src src/test) -add_executable(libguf_test src/test/test.cpp src/test/test_dbuf.cpp src/test/test_dict.cpp src/test/test_str.cpp src/test/test_ckdint.cpp src/test/test_utf8.cpp src/test/impls/init_impl.c src/test/impls/dbuf_impl.c src/test/impls/str_impl.c src/test/impls/dict_impl.c src/test/impls/rand_impl.c src/test/impls/sort_impl.c src/test/impls/linalg_impl.c src/test/impls/ckdint_impl.c) +add_executable(libguf_test src/test/test.cpp src/test/test_dbuf.cpp src/test/test_dict.cpp src/test/test_str.cpp src/test/test_ckdint.cpp src/test/test_utf8.cpp src/test/impls/init_impl.c src/test/impls/dbuf_impl.c src/test/impls/str_impl.c src/test/impls/dict_impl.c src/test/impls/rand_impl.c src/test/impls/sort_impl.c src/test/impls/linalg_impl.c src/test/impls/ckdint_impl.c src/test/impls/alloc_tracker_impl.c) target_include_directories(libguf_test PRIVATE src src/test) set_target_properties(libguf_example libguf_test PROPERTIES DEBUG_POSTFIX ${CMAKE_DEBUG_POSTFIX}) diff --git a/src/guf_alloc.h b/src/guf_alloc.h index 2d865a5..6a116b2 100644 --- a/src/guf_alloc.h +++ b/src/guf_alloc.h @@ -15,17 +15,11 @@ typedef struct guf_allocator { void *ctx; } guf_allocator; -typedef struct guf_alloc_meta { - size_t alloc_count, realloc_count, free_count; - ptrdiff_t allocated_bytes; - uint32_t alloc_id; -} guf_alloc_meta; - -typedef enum guf_alloc_fn_type { - GUF_ALLOC_FN_TYPE_ALLOC, - GUF_ALLOC_FN_TYPE_REALLOC, - GUF_ALLOC_FN_TYPE_FREE, -} guf_alloc_fn_type; +// typedef enum guf_alloc_fn_type { +// GUF_ALLOC_FN_TYPE_ALLOC, +// GUF_ALLOC_FN_TYPE_REALLOC, +// GUF_ALLOC_FN_TYPE_FREE, +// } guf_alloc_fn_type; /* GUF_ALLOC_MAX_BYTES: Largest number of bytes an allocated buffer of elements of TYPE can have. diff --git a/src/guf_alloc_libc.h b/src/guf_alloc_libc.h index c64917b..491382f 100644 --- a/src/guf_alloc_libc.h +++ b/src/guf_alloc_libc.h @@ -6,10 +6,11 @@ #define GUF_ALLOC_LIBC_H #include #include "guf_alloc.h" +#define GUF_ALLOC_TRACKER_IMPL_STATIC +#include "guf_alloc_tracker.h" typedef struct guf_libc_alloc_ctx { - guf_alloc_meta meta; - bool track_allocs; + guf_alloc_tracker tracker; bool zero_init; } guf_libc_alloc_ctx; @@ -17,13 +18,22 @@ static inline void *guf_libc_alloc(ptrdiff_t size, void *ctx) { GUF_ASSERT_RELEASE(size >= 0); guf_libc_alloc_ctx *alloc_ctx = (guf_libc_alloc_ctx*)ctx; + + void *res = NULL; if (size == 0) { - return NULL; + res = NULL; } else if (alloc_ctx && alloc_ctx->zero_init) { - return calloc(size, 1); + res = calloc(size, 1); } else { - return malloc(size); + res = malloc(size); } + + if (alloc_ctx && alloc_ctx->tracker.enabled) { + const bool succ = guf_track_alloc(&alloc_ctx->tracker, size); + GUF_ASSERT(succ); + } + + return res; } static inline void *guf_libc_realloc(void *ptr, ptrdiff_t old_size, ptrdiff_t new_size, void *ctx) @@ -37,21 +47,41 @@ static inline void *guf_libc_realloc(void *ptr, ptrdiff_t old_size, ptrdiff_t ne void *new_ptr = realloc(ptr, new_size); if (!new_ptr || new_size == 0) { - return NULL; + new_ptr = NULL; } else if (alloc_ctx && alloc_ctx->zero_init && new_size > old_size) { - ptrdiff_t len = new_size - old_size; + const ptrdiff_t len = new_size - old_size; GUF_ASSERT(len > 0); GUF_ASSERT(old_size + len == new_size); memset((char*)ptr + old_size, 0, len); // TODO: sketchy } + + if (alloc_ctx && alloc_ctx->tracker.enabled) { + const bool succ = guf_track_realloc(&alloc_ctx->tracker, old_size, new_size); + GUF_ASSERT(succ); + } + return new_ptr; } static inline void guf_libc_free(void *ptr, ptrdiff_t size, void *ctx) { - (void)ctx; - (void)size; free(ptr); + + guf_libc_alloc_ctx *alloc_ctx = (guf_libc_alloc_ctx*)ctx; + if (alloc_ctx && alloc_ctx->tracker.enabled) { + const bool succ = guf_track_free(&alloc_ctx->tracker, size); + GUF_ASSERT(succ); + } +} + +static inline guf_allocator *guf_libc_allocator_init(guf_allocator *a, guf_libc_alloc_ctx *ctx) +{ + GUF_ASSERT_RELEASE(a); + a->alloc = guf_libc_alloc; + a->realloc = guf_libc_realloc; + a->free = guf_libc_free; + a->ctx = ctx; + return a; } static guf_allocator guf_allocator_libc = { diff --git a/src/guf_alloc_tracker.c b/src/guf_alloc_tracker.c deleted file mode 100644 index c69c747..0000000 --- a/src/guf_alloc_tracker.c +++ /dev/null @@ -1,117 +0,0 @@ - -#include "guf_common.h" -#include "guf_alloc.h" -#include "math.h" - -typedef struct guf_alloc_tracker { - FILE *log, *err_log; - size_t alloc_count, realloc_count, free_count; - ptrdiff_t allocated_bytes; - uint32_t id; -} guf_alloc_tracker; - -static bool guf_track_alloc(guf_alloc_tracker *t, ptrdiff_t size) -{ - GUF_ASSERT(t); - GUF_ASSERT(size >= 0); - bool success = true; - if (t->err_log && t->alloc_count == SIZE_MAX) { - fprintf(t->err_log, "guf_alloc_track (id %" PRIu32 ") WARNING: alloc_count overflow\n", t->id); - //success = false; - } - - t->alloc_count = guf_add_saturated_size_t(t->alloc_count, 1); - - if (guf_add_is_overflow_ptrdiff(t->allocated_bytes, size)) { - if (t->err_log) { - fprintf(t->err_log, "guf_alloc_track (id %" PRIu32 ") ERROR: allocated_byte overflow\n", t->id); - } - success = false; - } - t->allocated_bytes = guf_add_saturated_ptrdiff(t->allocated_bytes, size); - if (t->allocated_bytes < 0) { - if (t->err_log) { - fprintf(t->err_log, "guf_alloc_track (id %" PRIu32 ") ERROR: allocated_bytes < 0\n", t->id); - } - success = false; - } - - if (t->log) { - fprintf(t->log, "guf_alloc_track (id %" PRIu32 "): alloc (%td bytes) %s\n", t->id, size, success ? "SUCCESS" : "FAILURE"); - } - return success; -} - - -static bool guf_track_realloc(guf_alloc_tracker *t, ptrdiff_t old_size, ptrdiff_t new_size) -{ - GUF_ASSERT(t); - GUF_ASSERT(old_size >= 0 && new_size >= 0); - bool success = true; - if (t->err_log && t->realloc_count == SIZE_MAX) { - fprintf(t->err_log, "guf_realloc_track (id %" PRIu32 ") WARNING: realloc_count overflow\n"); - //success = false; - } - t->realloc_count = guf_add_saturated_size_t(t->realloc_count, 1); - - if (old_size < 0 || new_size < 0) { - if (t->err_log) { - fprintf(t->err_log, "guf_realloc_track (id %" PRIu32 ") ERROR: old_size < 0 or new_size < 0\n"); - } - success = false; - } - - t->allocated_bytes = guf_sub_saturated_ptrdiff(t->allocated_bytes, old_size); - if (t->allocated_bytes < 0) { - success = false; - fprintf(t->err_log, "guf_realloc_track (id %" PRIu32 ") ERROR: allocated_bytes < 0 after subtracting old_size\n", t->id); - } - if (guf_add_is_overflow_ptrdiff(t->allocated_bytes, new_size)) { - success = false; - if (t->err_log) { - fprintf(t->err_log, "guf_realloc_track (id %" PRIu32 ") ERROR: allocated_bytes overflow \n"); - } - } - t->allocated_bytes = guf_add_saturated_ptrdiff(t->allocated_bytes, new_size); - - if (t->allocated_bytes < 0) { - success = false; - fprintf(t->err_log, "guf_realloc_track (id %" PRIu32 ") ERROR: allocated_bytes < 0 after adding new_size\n", t->id); - } - - if (t->log) { - fprintf(t->log, "guf_realloc_track (id %" PRIu32 "): realloc (from %td to %td bytes) %s", t->id, old_size, new_size, (success ? "SUCCESS" : "FAILURE")); - } - - return success; -} - -static bool guf_track_free(guf_alloc_tracker *t, ptrdiff_t size) -{ - GUF_ASSERT(t); - GUF_ASSERT(size >= 0); - - if (t->err_log && t->free_count == SIZE_MAX) { - fprintf(t->err_log, "guf_track_free (id %" PRIu32 ") WARNING: free_count overflow\n"); - } - bool success = true; - - if (size < 0) { - success = false; - if (t->err_log) { - fprintf(t->err_log, "guf_track_free (id %" PRIu32 ") ERROR: size < 0\n"); - } - } - - if (t->allocated_bytes < size) { - success = false; - if (t->err_log) { - fprintf(t->err_log, "guf_track_free (id %" PRIu32 ") ERROR: freed more bytes than allocated\n"); - } - } - t->allocated_bytes = guf_sub_saturated_ptrdiff(t->allocated_bytes, size); - - return success; -} - - diff --git a/src/guf_alloc_tracker.h b/src/guf_alloc_tracker.h new file mode 100644 index 0000000..d98ccf6 --- /dev/null +++ b/src/guf_alloc_tracker.h @@ -0,0 +1,200 @@ +#if defined(GUF_ALLOC_TRACKER_IMPL_STATIC) + #define GUF_ALLOC_TRACKER_KWRDS static inline +#else + #define GUF_ALLOC_TRACKER_KWRDS +#endif + +#ifndef GUF_ALLOC_TRACKER_H +#define GUF_ALLOC_TRACKER_H + +#include +#include "guf_common.h" + +typedef struct guf_alloc_tracker { + FILE *log, *err_log; + size_t alloc_count, realloc_count, free_count; + ptrdiff_t allocated_bytes; + uint32_t id; + bool enabled; +} guf_alloc_tracker; + +#if !defined(GUF_ALLOC_TRACKER_IMPL_STATIC) && !defined(GUF_ALLOC_TRACKER_IMPL) + GUF_ALLOC_TRACKER_KWRDS guf_alloc_tracker *guf_alloc_tracker_init(guf_alloc_tracker *t, uint32_t id, FILE *log, FILE *err_log); + GUF_ALLOC_TRACKER_KWRDS void guf_alloc_tracker_print(const guf_alloc_tracker *t, FILE *f); + GUF_ALLOC_TRACKER_KWRDS bool guf_alloc_tracker_found_leak(guf_alloc_tracker *t); + + GUF_ALLOC_TRACKER_KWRDS bool guf_track_alloc(guf_alloc_tracker *t, ptrdiff_t size); + GUF_ALLOC_TRACKER_KWRDS bool guf_track_realloc(guf_alloc_tracker *t, ptrdiff_t old_size, ptrdiff_t new_size); + GUF_ALLOC_TRACKER_KWRDS bool guf_track_free(guf_alloc_tracker *t, ptrdiff_t size); +#endif + +#if defined(GUF_ALLOC_TRACKER_IMPL_STATIC) || defined(GUF_ALLOC_TRACKER_IMPL) + +#include "guf_alloc.h" +#define GUF_MATH_CKDINT_IMPL_STATIC +#include "guf_math_ckdint.h" + +GUF_ALLOC_TRACKER_KWRDS guf_alloc_tracker *guf_alloc_tracker_init(guf_alloc_tracker *t, uint32_t id, FILE *log, FILE *err_log) +{ + GUF_ASSERT_RELEASE(t); + t->log = log; + t->err_log = err_log; + t->alloc_count = t->realloc_count = t->free_count = 0; + t->allocated_bytes = 0; + t->id = id; + t->enabled = true; + return t; +} + +GUF_ALLOC_TRACKER_KWRDS bool guf_alloc_tracker_found_leak(guf_alloc_tracker *t) +{ + GUF_ASSERT_RELEASE(t); + return (t->allocated_bytes != 0) || (t->alloc_count != t->free_count); +} + + +GUF_ALLOC_TRACKER_KWRDS void guf_alloc_tracker_print(const guf_alloc_tracker *t, FILE *f) +{ + GUF_ASSERT(t); + if (!f) { + f = stdout; + } + + if (!t) { + fprintf(f, "guf_alloc_tracker_fprint: guf_alloc_tracker is NULL"); + return; + } + + fprintf(f, + "guf_alloc_tracker (id = %" PRIu32 "):\n" + "allocated_bytes: %td\n" + "alloc_count: %zu\n" + "realloc_count: %zu\n" + "free_count: %zu\n", + t->id, t->allocated_bytes, t->alloc_count, t->realloc_count, t->free_count + ); + +} + +GUF_ALLOC_TRACKER_KWRDS bool guf_track_alloc(guf_alloc_tracker *t, ptrdiff_t size) +{ + GUF_ASSERT(t); + GUF_ASSERT(size >= 0); + + bool success = true; + + if (guf_saturating_add_size_t(t->alloc_count, 1, &t->alloc_count) != GUF_MATH_CKD_SUCCESS && t->err_log) { + fprintf(t->err_log, "WARNING in guf_track_alloc (id %" PRIu32 "): alloc_count reached SIZE_MAX\n", t->id); + } + + if (guf_saturating_add_ptrdiff_t(t->allocated_bytes, size, &t->allocated_bytes) != GUF_MATH_CKD_SUCCESS) { + if (t->err_log) { + fprintf(t->err_log, "ERROR in guf_track_alloc (id %" PRIu32 "): allocated_byte overflow\n", t->id); + } + success = false; + } + + if (t->allocated_bytes < 0) { + if (t->err_log) { + fprintf(t->err_log, "ERROR in guf_track_alloc (id %" PRIu32 "): allocated_bytes < 0\n", t->id); + } + success = false; + } + + if (t->log) { + fprintf(t->log, "guf_alloc_tracker (id %" PRIu32 "): alloc (%td bytes) %s\n", t->id, size, success ? "SUCCESS" : "FAILURE"); + } + return success; +} + + +GUF_ALLOC_TRACKER_KWRDS bool guf_track_realloc(guf_alloc_tracker *t, ptrdiff_t old_size, ptrdiff_t new_size) +{ + GUF_ASSERT(t); + GUF_ASSERT(old_size >= 0 && new_size >= 0); + bool success = true; + + if (guf_saturating_add_size_t(t->realloc_count, 1, &t->realloc_count) && t->err_log) { + fprintf(t->err_log, "WARNING in guf_track_realloc (id %" PRIu32 "): realloc_count reached SIZE_MAX\n", t->id); + } + + if (old_size < 0 || new_size < 0) { + success = false; + if (t->err_log) { + fprintf(t->err_log, "ERROR in guf_track_realloc (id %" PRIu32 "): old_size < 0 or new_size < 0\n", t->id); + } + } + + if (guf_saturating_sub_ptrdiff_t(t->allocated_bytes, old_size, &t->allocated_bytes)) { + success = false; + if (t->err_log) { + fprintf(t->err_log, "ERROR in guf_track_realloc (id %" PRIu32 "): allocated_bytes - old_size under/overflows\n", t->id); + } + } + if (t->allocated_bytes < 0) { + success = false; + fprintf(t->err_log, "ERROR in guf_track_realloc (id %" PRIu32 "): allocated_bytes < 0 after subtracting old_size\n", t->id); + } + + if (guf_saturating_add_ptrdiff_t(t->allocated_bytes, new_size, &t->allocated_bytes)) { + success = false; + if (t->err_log) { + fprintf(t->err_log, "ERROR in guf_track_realloc (id %" PRIu32 "): allocated_bytes overflow \n", t->id); + } + } + if (t->allocated_bytes < 0) { + success = false; + fprintf(t->err_log, "ERROR in guf_track_realloc (id %" PRIu32 "): allocated_bytes < 0 after adding new_size\n", t->id); + } + + if (t->log) { + fprintf(t->log, "guf_alloc_tracker (id %" PRIu32 "): realloc (from %td to %td bytes) %s\n", t->id, old_size, new_size, (success ? "SUCCESS" : "FAILURE")); + } + + return success; +} + +GUF_ALLOC_TRACKER_KWRDS bool guf_track_free(guf_alloc_tracker *t, ptrdiff_t size) +{ + GUF_ASSERT(t); + GUF_ASSERT(size >= 0); + bool success = true; + + if (guf_saturating_add_size_t(t->free_count, 1, &t->free_count) && t->err_log) { + fprintf(t->err_log, "WARNING in guf_track_free (id %" PRIu32 "): free_count reached SIZE_MAX\n", t->id); + } + + if (size < 0) { + success = false; + if (t->err_log) { + fprintf(t->err_log, "ERROR in guf_track_free (id %" PRIu32 "): size < 0\n", t->id); + } + } + + if (t->allocated_bytes < size) { + success = false; + if (t->err_log) { + fprintf(t->err_log, "ERROR in guf_track_free (id %" PRIu32 "): freed more bytes than allocated\n", t->id); + } + } + if (guf_saturating_sub_ptrdiff_t(t->allocated_bytes, size, &t->allocated_bytes)) { + success = false; + if (t->err_log) { + fprintf(t->err_log, "ERROR in guf_track_free (id %" PRIu32 "): allocated_bytes - size under/overflows\n", t->id); + } + } + + if (t->log) { + fprintf(t->log, "guf_alloc_tracker (id %" PRIu32 "): free (%td bytes) %s\n", t->id, size, (success ? "SUCCESS" : "FAILURE")); + } + + return success; +} + +#endif /* End impl */ + +#endif /* End header-guard */ + +#undef GUF_ALLOC_TRACKER_KWRDS +#undef GUF_ALLOC_TRACKER_IMPL +#undef GUF_ALLOC_TRACKER_IMPL_STATIC diff --git a/src/guf_math_ckdint.h b/src/guf_math_ckdint.h index 233fc5c..0fa5172 100644 --- a/src/guf_math_ckdint.h +++ b/src/guf_math_ckdint.h @@ -1,11 +1,6 @@ /* is parametrized: no */ -#if defined(GUF_MATH_CKDINT_IMPL_STATIC) - #define GUF_MATH_CKDINT_KWRDS static inline -#else - #define GUF_MATH_CKDINT_KWRDS -#endif /* // Functions for safely checking for over- and underflow of arithmetic operations @@ -85,6 +80,8 @@ typedef enum guf_math_ckd_result {GUF_MATH_CKD_SUCCESS = 0, GUF_MATH_CKD_OVERFLOW, GUF_MATH_CKD_UNDERFLOW} guf_math_ckd_result; +#if !defined(GUF_MATH_CKDINT_IMPL_STATIC) && !defined(GUF_MATH_CKDINT_IMPL) + // Signed integer arithmetic checks (generated with libguf/tools/ckdint-gen.py) GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_int(int a, int b); @@ -262,6 +259,7 @@ GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_add_size_t(size_t a, size GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_sub_size_t(size_t a, size_t b, size_t *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_size_t(size_t a, size_t b, size_t *result); +#endif #if defined(GUF_MATH_CKDINT_IMPL) || defined(GUF_MATH_CKDINT_IMPL_STATIC) #include "guf_assert.h" @@ -2063,3 +2061,4 @@ GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_size_t(size_t a, size #undef GUF_MATH_CKDINT_IMPL #undef GUF_MATH_CKDINT_IMPL_STATIC +#undef GUF_MATH_CKDINT_KWRDS diff --git a/src/test/example.c b/src/test/example.c index 5f17615..a32b17c 100644 --- a/src/test/example.c +++ b/src/test/example.c @@ -59,7 +59,7 @@ int main(void) guf_platform_assert_native_word_bits(); guf_allocator test_allocator = guf_allocator_libc; - guf_libc_alloc_ctx test_allocator_ctx = {.zero_init = true, .track_allocs = false}; + guf_libc_alloc_ctx test_allocator_ctx = {.zero_init = true, .tracker = (guf_alloc_tracker){.enabled = false}}; test_allocator.ctx = &test_allocator_ctx; dict_cstr_int ht; diff --git a/src/test/impls/alloc_tracker_impl.c b/src/test/impls/alloc_tracker_impl.c new file mode 100644 index 0000000..5f41f5a --- /dev/null +++ b/src/test/impls/alloc_tracker_impl.c @@ -0,0 +1,2 @@ +#define GUF_ALLOC_TRACKER_IMPL +#include "guf_alloc_tracker.h" diff --git a/src/test/test_dbuf.cpp b/src/test/test_dbuf.cpp index 7a089a8..47e4d7f 100644 --- a/src/test/test_dbuf.cpp +++ b/src/test/test_dbuf.cpp @@ -16,8 +16,11 @@ void DbufIntTest::run() return; } + // allocator_ctx.tracker.log = fopen("alloc_log.txt", "w"); + // allocator_ctx.tracker.err_log = fopen("alloc_err_log.txt", "w"); + dbuf_int dbuf {}; - dbuf_int_init(&dbuf, 0, &guf_allocator_libc); + dbuf_int_init(&dbuf, 0, &allocator); push_check_name("test_push"); @@ -29,7 +32,7 @@ void DbufIntTest::run() dbuf_int_free(&dbuf, NULL); TEST_CHECK(dbuf.size == 0 && dbuf.capacity == 0 && dbuf.data == NULL); - dbuf_int_init(&dbuf, 24, &guf_allocator_libc); + dbuf_int_init(&dbuf, 24, &allocator); TEST_CHECK(dbuf.size == 0 && dbuf.capacity == 24 && dbuf.data); test_push(&dbuf, 365); @@ -57,6 +60,12 @@ void DbufIntTest::run() test_insert_remove(2049); pop_check_name(); + + TEST_CHECK(!guf_alloc_tracker_found_leak(&allocator_ctx.tracker)); + // guf_alloc_tracker_print(&allocator_ctx.tracker, stdout); + // puts(""); + // fclose(allocator_ctx.tracker.log); + // fclose(allocator_ctx.tracker.err_log); } std::vector DbufIntTest::dbuf_to_vec(dbuf_int *dbuf) @@ -97,7 +106,7 @@ void DbufIntTest::test_push(dbuf_int *dbuf, int n) void DbufIntTest::test_insert_remove(int n) { dbuf_int dbuf = {}; - dbuf_int_init(&dbuf, 0, &guf_allocator_libc); + dbuf_int_init(&dbuf, 0, &allocator); std::vector vec = dbuf_to_vec(&dbuf); guf_err err = GUF_ERR_NONE; @@ -222,6 +231,9 @@ void DbufCstringTest::run() return; } + // allocator_ctx.tracker.log = fopen("alloc_log.txt", "w"); + // allocator_ctx.tracker.err_log = fopen("alloc_err_log.txt", "w"); + push_check_name("push_insert_erase"); for (int i = 1; i <= 32; ++i) { @@ -235,7 +247,7 @@ void DbufCstringTest::run() test_push_insert_erase(2048, 11); dbuf_heap_cstr str_dbuf = {}; - dbuf_heap_cstr_init(&str_dbuf, 0, &guf_allocator_libc); + dbuf_heap_cstr_init(&str_dbuf, 0, &allocator); std::vector str_vec {}; for (int i = 0; i < 512; ++i) { @@ -261,6 +273,12 @@ void DbufCstringTest::run() test_find(42); test_find(129); pop_check_name(); + + TEST_CHECK(!guf_alloc_tracker_found_leak(&allocator_ctx.tracker)); + // guf_alloc_tracker_print(&allocator_ctx.tracker, stdout); + // puts(""); + // fclose(allocator_ctx.tracker.log); + // fclose(allocator_ctx.tracker.err_log); } void DbufCstringTest::test_iter(std::vector& str_vec, dbuf_heap_cstr *str_dbuf, int step) @@ -324,7 +342,7 @@ void DbufCstringTest::test_push_insert_erase(int n, ptrdiff_t start_cap) { std::vector str_vec; dbuf_heap_cstr str_dbuf {}; - dbuf_heap_cstr_init(&str_dbuf, start_cap, &guf_allocator_libc); + dbuf_heap_cstr_init(&str_dbuf, start_cap, &allocator); for (int i = 0; i < n; ++i) { constexpr int BUF_SZ = 128; @@ -449,7 +467,7 @@ void DbufCstringTest::test_find(int n) std::vector str_vec {}; dbuf_heap_cstr str_dbuf = {}; - dbuf_heap_cstr_init(&str_dbuf, 0, &guf_allocator_libc); + dbuf_heap_cstr_init(&str_dbuf, 0, &allocator); for (int i = 0; i < n; ++i) { constexpr int BUF_SZ = 128; diff --git a/src/test/test_dbuf.hpp b/src/test/test_dbuf.hpp index 2eb3db7..a2ca207 100644 --- a/src/test/test_dbuf.hpp +++ b/src/test/test_dbuf.hpp @@ -6,14 +6,24 @@ extern "C" { #include "guf_alloc_libc.h" #include "impls/dbuf_impl.h" + #include "guf_alloc_libc.h" } struct DbufIntTest : public Test { - DbufIntTest(const std::string& name) : Test(name) {}; + DbufIntTest(const std::string& name) : Test(name) + { + allocator_ctx.zero_init = false; + guf_alloc_tracker_init(&allocator_ctx.tracker, 1, NULL, NULL); + guf_libc_allocator_init(&allocator, &allocator_ctx); + } + void run() override; private: + guf_allocator allocator; + guf_libc_alloc_ctx allocator_ctx; + std::vector dbuf_to_vec(dbuf_int *dbuf); void test_push(dbuf_int *dbuf, int n); void test_insert_remove(int n); @@ -22,10 +32,19 @@ private: struct DbufCstringTest : public Test { - DbufCstringTest(std::string name) : Test(name) {}; + DbufCstringTest(std::string name) : Test(name) + { + allocator_ctx.zero_init = false; + guf_alloc_tracker_init(&allocator_ctx.tracker, 2, NULL, NULL); + guf_libc_allocator_init(&allocator, &allocator_ctx); + } + void run() override; private: + guf_allocator allocator; + guf_libc_alloc_ctx allocator_ctx; + void test_iter(std::vector& str_vec, dbuf_heap_cstr *str_dbuf, int step = 1); void test_push_insert_erase(int n, ptrdiff_t start_cap = 0); void test_find(int n = 32); diff --git a/todo.txt b/todo.txt index 5c7b423..fcf7efc 100644 --- a/todo.txt +++ b/todo.txt @@ -1,11 +1,7 @@ -- guf_wrapping_mul_TYPE: Don't rely on implementation defined behaviour - -- header guards for optional int64_t types maybe... +- guf_wrapping_mul_TYPE: Not 100 % sure if it does not depend on implementation defined behaviour, but it shouldn't - sort: add cpp #ifdef to remove restrict from declaration -- separate impl and headers from tests (for compile perf) - - tests for guf_dict with GUF_DICT_64_BIT_IDX (and also hash32/hash64); maybe pass kv_type to insert to avoid copy - dict elems shrink to fit; allow to pass GUF_DBUF_USE_GROWTH_FAC_ONE_POINT_FIVE; start capacity (for elems and kv_indices?) - dict: if load factor is high due to mostly tombstones, just try rehashing without resizing first? @@ -15,11 +11,6 @@ - guf_stack, guf_queue, guf_dqueue, guf_prio_queue (using a heap), guf_ringbuf -- track allocs for test (implement alloc tracker): - - each thread needs its own alloc and alloc_ctx; don't track granular, give each allocator it's unique id maybe? - -- potential idea for alloc: instead of using a pointer (8 or 4 bytes), use a 2 byte id to save space (and avoid dangling pointers): - - no guf_init.h - unicode normalisation diff --git a/tools/ckdint-gen.py b/tools/ckdint-gen.py index e97913a..bdd049e 100644 --- a/tools/ckdint-gen.py +++ b/tools/ckdint-gen.py @@ -408,7 +408,10 @@ if __name__ == "__main__": """)) + + print("#if !defined(GUF_MATH_CKDINT_IMPL_STATIC) && !defined(GUF_MATH_CKDINT_IMPL)") print(code_header) + print("#endif") print("#if defined(GUF_MATH_CKDINT_IMPL) || defined(GUF_MATH_CKDINT_IMPL_STATIC)") print('#include "guf_assert.h"') @@ -417,5 +420,6 @@ if __name__ == "__main__": print("#endif") + print("#undef GUF_MATH_CKDINT_KWRDS") print("#undef GUF_MATH_CKDINT_IMPL") print("#undef GUF_MATH_CKDINT_IMPL_STATIC\n")