This is my first time doing any kind of serious coding in C. I watched a Youtube video on what an Arena Allocator should do and I tried my best to make an implementation for it.
As of now, we have the arena itself and a way to handle errors in the arena. I prefer a way to just warn the programmer about errors and put on them to decide what to do with it (be it crash or something else).
Any criticism are greatly appreciated!
/* ArenaAlloc.h */
#ifndef ARENA_ALLOC_H
#define ARENA_ALLOC_H
#include <stdlib.h>
#include <stdint.h>
#include <assert.h>
#include <string.h>
#include <stdio.h>
#define KB(x) (x*1024)
typedef char* Arena_ptr;
typedef struct {
size_t offset;
Arena_ptr buffer;
size_t size;
} Arena;
enum Arena_ErrorType
{
ARENA_ERR_NONE,
ARENA_ERR_MALLOC,
ARENA_ERR_NOT_ENOUGH_SPACE
};
typedef struct {
char errMsg[256];
size_t requested;
size_t available;
uint8_t status;
} Arena_Error;
void Arena_init(Arena *arena, size_t size, Arena_Error *err);
// Allocates space in the arena (in bytes) and returns a pointer to the location
void *Arena_alloc(Arena *arena, size_t size, Arena_Error *err);
// Cleans the array and resets the offset back to the start
void Arena_clean(Arena *arena);
void Arena_delete(Arena *arena);
#endif /* ARENA_ALLOC_H */
/* ArenaAlloc.c */
#include "ArenaAlloc.h"
void Arena_init(Arena *arena, size_t size, Arena_Error *err)
{
err->status = ARENA_ERR_NONE;
*arena = (Arena) {
.offset = 0,
.buffer = malloc(size),
.size = size
};
if (!arena->buffer)
{
err->status = ARENA_ERR_MALLOC;
err->requested = size;
err->available = 0;
strcpy(err->errMsg, "Could not allocate memory for the arena");
return;
}
Arena_clean(arena);
}
void *Arena_alloc(Arena *arena, size_t size, Arena_Error *err)
{
if (arena->offset + size > arena->size)
{
err->status = ARENA_ERR_NOT_ENOUGH_SPACE;
err->requested = size;
err->available = arena->size - arena->offset;
sprintf(err->errMsg, "Not enough space. Requested: %zu\nAvailable: %zu", size, arena->size - arena->offset);
return NULL;
}
Arena_ptr ptr = arena->buffer;
arena->offset = size;
arena->buffer += arena->offset;
return ptr;
}
void Arena_clean(Arena *arena)
{
arena->buffer -= arena->offset;
for (size_t i = 0; i < arena->size; i++, arena->buffer++)
*arena->buffer = 0;
arena->buffer -= arena->size;
arena->offset = 0;
}
void Arena_delete(Arena *arena)
{
Arena_clean(arena);
free(arena->buffer);
}
here's a main.c that i've been using to debug it:
#include "ArenaAlloc.h"
int main(int argc, char const *argv[])
{
Arena myArena = {};
Arena_Error err = {};
Arena_init(&myArena, KB(10), &err);
if (err.status)
printf("%s\n", err.errMsg);
int *ptr = Arena_alloc(&myArena, sizeof(int) * 6, &err);
if (!ptr)
printf("%s\n", err.errMsg);
size_t i;
for (i = 0; i < 6; i++, ptr++)
{
*ptr = KB(i);
printf("ptr: %p\tvalue: %d\n", ptr, *ptr);
}
ptr -= i;
for (i = 0; i < 6; i++, ptr++)
{
printf("myArena.buffer: %p\tvalue: %d\n", ptr, *ptr);
}
Arena_delete(&myArena);
return 0;
}
free? \$\endgroup\$