From 19e27ca78233b752759b7b8365e31982937db615 Mon Sep 17 00:00:00 2001 From: Warwick Date: Mon, 24 Nov 2025 09:58:04 +0000 Subject: [PATCH] Fixed tree deallocation by preventing the creation of copies on arena initialisation --- src/arena_allocator.c | 36 +++++++++++++++++++++++++++--------- src/arena_allocator.h | 4 +++- src/main.c | 19 +++++++++---------- 3 files changed, 39 insertions(+), 20 deletions(-) diff --git a/src/arena_allocator.c b/src/arena_allocator.c index 233d6e2..86057df 100644 --- a/src/arena_allocator.c +++ b/src/arena_allocator.c @@ -2,6 +2,7 @@ #include #include #include +#include #define DEFAUL_REGION_SIZE 1048576 /* 8 * 1024 * 1024 = 8MB */ @@ -12,33 +13,44 @@ Region *new_region(size_t capacity) { Region *region = malloc(capacity + sizeof(Region)); assert(region != NULL); *region = (Region){.next = NULL, .capacity = capacity, .cursor = 0}; + + // Zero initialise memory + memset(region->data, 0, capacity); + return region; } -Arena arena_init(Arena *parent, size_t capacity) { +Arena *arena_init(Arena *parent, size_t capacity) { Region *region = new_region(capacity); if (parent != NULL) { // Allocate new arena in parent to reduce likelyhood of loss Arena *current_arena = arena_alloc(parent, sizeof(Arena)); - *current_arena = - (Arena){.begin = region, .end = region, .child = NULL, .sibling = NULL}; + *current_arena = (Arena){.is_root = false, + .begin = region, + .end = region, + .child = NULL, + .sibling = NULL}; // if parent has no children this arena is now it's child if (parent->child == NULL) { parent->child = current_arena; - return *current_arena; + return current_arena; } // Push the arena onto the first childs sibling list current_arena->sibling = parent->child; parent->child = current_arena; - return *current_arena; + return current_arena; } - // This is the root of the arena tree - Arena arena = { - .begin = region, .end = region, .child = NULL, .sibling = NULL}; + // Create root of arena tree + Arena *arena = malloc(sizeof(Arena)); + *arena = (Arena){.is_root = true, + .begin = region, + .end = region, + .child = NULL, + .sibling = NULL}; return arena; } @@ -62,7 +74,11 @@ void arena_deinit(Arena *arena) { region = next_region; } - *arena = (Arena){.begin = NULL, .end = NULL}; + arena->begin = NULL; + arena->end = NULL; + if (arena->is_root) { + free(arena); + } } void *arena_alloc(Arena *arena, size_t size) { @@ -79,6 +95,8 @@ void *arena_alloc(Arena *arena, size_t size) { void *result = ®ion->data[region->cursor]; region->cursor += size; + // TODO: only align when needed + size = (size + 7) & ~7; // align size increase to multiple of 8 return result; } diff --git a/src/arena_allocator.h b/src/arena_allocator.h index 423eedf..6dbe772 100644 --- a/src/arena_allocator.h +++ b/src/arena_allocator.h @@ -1,5 +1,6 @@ #pragma once +#include #include typedef struct Region_s Region; @@ -12,13 +13,14 @@ struct Region_s { typedef struct Arena_s Arena; struct Arena_s { + bool is_root; Arena *child; Arena *sibling; Region *begin; Region *end; }; -Arena arena_init(Arena *parent, size_t capacity); +Arena *arena_init(Arena *parent, size_t capacity); void arena_deinit(Arena *arena); void *arena_alloc(Arena *arena, size_t size); diff --git a/src/main.c b/src/main.c index 9eeb1ca..a0404d2 100644 --- a/src/main.c +++ b/src/main.c @@ -14,23 +14,22 @@ int main(int argc, char *argv[]) { // arena allocation test printf("Allocation test\n"); - Arena global_arena = arena_init(NULL, 0); - for (int i = 0; i <= 1048576+100; i++) { - int *number = arena_alloc(&global_arena, sizeof(int)); + Arena *global_arena = arena_init(NULL, 0); + for (int i = 0; i <= 1048576 + 100; i++) { + int *number = arena_alloc(global_arena, sizeof(int)); *number = 42; } - printf("children test\n"); - // arena children test - Arena child_arena = arena_init(&global_arena, 0); - //Arena sibling_arena = arena_init(&global_arena, 0); - //Arena grandchild_arena = arena_init(&child_arena, 0); + printf("children test\n"); + Arena *child_arena = arena_init(global_arena, 0); + Arena *sibling_arena = arena_init(global_arena, 0); + Arena *grandchild_arena = arena_init(child_arena, 0); - arena_deinit(&global_arena); + printf("deinit test\n"); + arena_deinit(global_arena); printf("tests complete\n"); - } /*int main(int argc, char *argv[]) {