{"id":30653776,"url":"https://github.com/rax-x/arena-allocator","last_synced_at":"2025-08-31T08:03:19.899Z","repository":{"id":306609196,"uuid":"1026430351","full_name":"Rax-x/arena-allocator","owner":"Rax-x","description":"C Arena Allocator: A Minimal, Header-Only Solution for Efficient Memory Management 🏟️","archived":false,"fork":false,"pushed_at":"2025-07-26T17:03:58.000Z","size":27,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-07-26T19:57:55.339Z","etag":null,"topics":["arena","arena-allocator","c","c99","clanguage","header-only","memory-allocation","stb","stb-style"],"latest_commit_sha":null,"homepage":"","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Rax-x.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-07-25T22:00:25.000Z","updated_at":"2025-07-26T17:04:01.000Z","dependencies_parsed_at":"2025-07-26T19:57:57.642Z","dependency_job_id":"13c98329-1a8c-4359-aba6-8e23164e2c0a","html_url":"https://github.com/Rax-x/arena-allocator","commit_stats":null,"previous_names":["rax-x/arena-allocator"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/Rax-x/arena-allocator","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Rax-x%2Farena-allocator","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Rax-x%2Farena-allocator/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Rax-x%2Farena-allocator/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Rax-x%2Farena-allocator/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Rax-x","download_url":"https://codeload.github.com/Rax-x/arena-allocator/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Rax-x%2Farena-allocator/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":272953955,"owners_count":25021136,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-31T02:00:09.071Z","response_time":79,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["arena","arena-allocator","c","c99","clanguage","header-only","memory-allocation","stb","stb-style"],"created_at":"2025-08-31T08:03:17.571Z","updated_at":"2025-08-31T08:03:19.891Z","avatar_url":"https://github.com/Rax-x.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"# 🏟️ Arena allocator\n\nWhen I develop toy compilers, I have to deal with data structures allocation and deallocation and it's really painful with C,\nto make my life easier I choose arena allocators, because I don't have to deal with memory deallocation and I'm sure\nthat at some point in the program, all the allocated memory is released. This is the implementation that always I copy\nand paste from a project to another.\n\n\u003e[!IMPORTANT]\n\u003eThis library is written in **C99**.\n\n# 🌱 How to Use It in Your Project\nThis library is designed for easy integration into your C projects. \nIt follows the [stb-style](https://github.com/nothings/stb), which means you don't need \nto compile it separately or link against any `.lib` or `.so` files.\n\nFor more information about the stb-style, you can read this [guide](https://github.com/nothings/stb/blob/master/docs/stb_howto.txt).\n\n## Basic Usage\nTo use the arena allocator in your project, simply include the `arena.h` header file. In one (and only one) of your `.c` source files, \nyou must define `ARENA_IMPLEMENTATION` before including `arena.h`. \nThis tells the preprocessor to include the function definitions in that specific compilation unit.\n\n```c\n// In one of your .c files (e.g., main.c)\n#define ARENA_IMPLEMENTATION\n#include \"arena.h\"\n\n// Your application code...\n```\n\n## Advanced Usage: Separating Implementation\nFor larger projects, or to improve compilation times, you might prefer to put the implementation code \nin a dedicated `.c` file. This is a common practice with stb-style libraries.\n\n**1. Create a separate implementation file (e.g., arena_impl.c):**\n```c\n// arena_impl.c\n// This file will contain the actual function definitions for the arena allocator.\n#define ARENA_IMPLEMENTATION\n#include \"arena.h\"\n```\n\n**2. Include the header in other project files (e.g., my_project_file.c):**\n```c\n// my_project_file.c\n// Other source files in your project can simply include the header.\n#include \u003cstdio.h\u003e // Example standard library include\n#include \"arena.h\" // Include the arena allocator header\n\n// Your project's code that uses the arena allocator\n// ...\n```\n\n# 🧪 Testing\n\nAt the moment I've implemented only the basic test cases. \nIf other test cases come up in your mind, open an **issue**, and we will discuss it.\n\nTo execute the tests, open your terminal and run the following command:\n```bash\nmake test\n```\n\n# 📔 API\n\n## Constants\n\n\u003e[!NOTE]\n\u003e These constants aren't used anywhere in the implementation code,\n\u003e they're not the default value for nothing or anything like this, simply\n\u003e rappresents values that I usually use.\n\n- `PAGE_SIZE`: defines the size of a 4KB page.\n- `HUGE_PAGE_SIZE`: defines the size of a 16KB page.\n\n## Data Structures\n\n```c\ntypedef struct _arena_chunk {\n    struct _arena_chunk* next;\n    size_t size;\n    size_t used;\n    uint8_t data[]; // Flexible array member\n} arena_chunk_t;\n```\n\nThis structure represents a single block of memory within the arena.\n\n- `next`: A pointer to the next `arena_chunk_t` in the linked list of chunks. This allows the arena to grow by adding more chunks as needed.\n- `size`: The total size (in bytes) of the data buffer within this chunk.\n- `used`: The amount of memory (in bytes) currently allocated from this chunk.\n- `data[]`: A flexible array member ([FAM](https://en.wikipedia.org/wiki/Flexible_array_member)).\n            This means that the actual memory for the chunk's data is allocated immediately after the `arena_chunk_t` structure itself.\n            This allows for efficient memory usage without additional pointer indirection.\n\n--- \n```c\ntypedef struct {\n    arena_chunk_t* begin;\n    arena_chunk_t* end;\n} arena_t;\n```\n\nThis structure represents the arena itself, managing the collection of arena_chunk_t blocks.\n\n- `begin`: A pointer to the first `arena_chunk_t` in the linked list.\n- `end`: A pointer to the last (current) `arena_chunk_t` in the linked list. New allocations are primarily attempted from this chunk.\n\n## Functions\n\n```c\n  arena_t create_arena(size_t size);\n```\n\nInitializes a new memory arena. It allocates the first `arena_chunk_t` with the specified size.\n\n**Parameters:**\n - `size`: The desired size for the memory chunks in the arena.\n\n**Returns:** An `arena_t` structure representing the newly created and initialized arena.\n\n---\n\n```c\n  void* arena_alloc(arena_t* restrict arena, size_t size);\n```\n\nAllocates a block of memory of `size` bytes from the specified arena.\n\nIt first attempts to allocate from the end chunk of the arena.\nIf the current chunk does not have enough contiguous free space, a new chunk is allocated (with the same size as the previous) \nand appended to the arena's linked list of chunks. The allocation then proceeds from this new chunk.\n\n\u003e[!NOTE]\n\u003e If the `ARENA_REDUCE_FRAGMENTATION` is defined, before allocating a new chunk,\n\u003e the arena linked list of chunks is scanned, trying to find a _\"hole\"_ big enough\n\u003e for current allocation. In this way we'll reduce the internal chunk fragmentation.\n\n**Parameters:**\n - `arena`: A pointer to the `arena_t` structure from which to allocate memory.\n - `size`: The number of bytes to allocate.\n\n**Returns:** A `void*` pointer to the newly allocated memory block, or `NULL` if `size` is less than or equal to zero. The returned memory is not initialized.\n\n---\n\n```c\n  void* arena_realloc(arena_t* restrict arena, \n                      const void* restrict ptr, \n                      size_t old_size, \n                      size_t new_size);\n```\nResizes a previously allocated memory block `ptr` within the arena to `new_size` bytes.\n\nUnlike standard realloc, it will allocate a new block of `new_size` bytes using `arena_alloc`, copy the contents from the old `ptr` to the new block, \nand then effectively abandon the old block (as arena allocators typically don't support individual deallocations).\n\nIt's important to note that `arena_realloc` might be less efficient than realloc in a general-purpose allocator \nbecause it often involves copying data and cannot truly \"free\" the old space.\n\n**Parameters:**\n - `arena`: A pointer to the `arena_t` structure.\n - `ptr`: A pointer to the memory block previously allocated by `arena_alloc`. If `ptr` is `NULL`, this function behaves like `arena_alloc`.\n - `old_size`: The original size of the memory block `ptr`. An incorrect `old_size` will result in undefined behavior.\n - `new_size`: The new desired size for the memory block.\n\n**Returns:** A `void*` pointer to the new memory block, or `NULL` if the `size` is less or equal to zero.\n\n---\n\n```c\n  char* arena_strdup(arena_t* restrict arena, const char* restrict str);\n```\n\nDuplicates a null-terminated string `str` into memory allocated from the arena. It allocates enough space for the string plus the null terminator.\n\n**Parameters:**\n - `arena`: A pointer to the `arena_t` structure.\n - `str`: The null-terminated string to duplicate.\n\n**Returns:** A `char*` pointer to the duplicated string within the arena.\n\n---\n\n```c\n  char* arena_strndup(arena_t* restrict arena, const char* restrict str, size_t length);\n```\n\nDuplicates at most `length` characters from the string `str` into memory allocated from the arena. The duplicated string will be null-terminated.\n\n**Parameters:**\n- `arena`: A pointer to the `arena_t` structure.\n- `str`: The source string.\n- `length`: The maximum number of characters to duplicate from `str`.\n\n**Returns:** A `char*` pointer to the duplicated string within the arena.\n\n--- \n\n```c\n  void destroy_arena(arena_t* restrict arena);\n```\n\nFrees all memory associated with the arena. This function iterates through all `arena_chunk_t` blocks in the linked list and deallocates them.\nAfter this call, the `arena_t` structure and any pointers obtained from `arena_alloc` within this arena become invalid.\n\nParameters:\n- `arena`: A pointer to the `arena_t` structure to destroy.\n\n## Debugging Functions (ARENA_DEBUG_MODE)\n\nThese functions are available only when `ARENA_DEBUG_MODE` is defined, \nproviding introspection into the arena's state for debugging and profiling purposes.\n\n---\n\n```c\n  int arena_get_chunks_count(const arena_t* restrict arena);\n```\n\nReturns the total number of `arena_chunk_t` blocks currently allocated in the arena.\n\n**Parameters:**\n- `arena`: A pointer to the `arena_t` structure.\n\n**Returns:** An `int` representing the count of chunks.\n\n---\n```c\n  size_t arena_get_available_space_of(const arena_t* restrict arena, int chunk_index);\n```\nReturns the available (unused) space in a specific chunk identified by its `chunk_index`.\n\n**Parameters:**\n- `arena`: A pointer to the `arena_t` structure.\n- `chunk_index`: The 0-based index of the chunk to query.\n\n**Returns:** A `size_t` representing the available space in bytes for that chunk.\n\n---\n```c\n  size_t arena_get_current_available_space(const arena_t* restrict arena);\n```\n\nReturns the available (unused) space in the current chunk of the arena.\n\n**Parameters:**\n- `arena`: A pointer to the `arena_t` structure.\n\n**Returns:** A `size_t` representing the available space in bytes in the current chunk.\n\n---\n```c\n  size_t arena_get_used_space_of(const arena_t* restrict arena, int chunk_index);\n```\n\nReturns the used space in a specific chunk identified by its `chunk_index`.\n\n**Parameters:**\n- `arena`: A pointer to the `arena_t` structure.\n- `chunk_index`: The 0-based index of the chunk to query.\n\n**Returns:** A `size_t` representing the used space in bytes for that chunk.\n\n---\n```c\n  size_t arena_get_current_used_space(const arena_t* restrict arena);\n```\n\nReturns the used space in the current chunk of the arena.\n\n**Parameters:**\n- `arena`: A pointer to the `arena_t` structure.\n\n**Returns:** A `size_t` representing the used space in bytes in the current chunk.\n\n# ✨ Customization\n\nYou can integrate your custom `malloc()` and `free()` implementations with the library \nby defining the `ARENA_MALLOC` and `ARENA_FREE` macros. \nThis allows the library to use your preferred memory management functions.\n\n\u003e[!NOTE]\n\u003e By default, `stdlib.h`'s malloc and free are used.\n\n```c\n#include \"xmalloc.h\" // Your custom memory allocation headers\n\n#define ARENA_MALLOC xmalloc\n#define ARENA_FREE xfree\n\n#define ARENA_IMPLEMENTATION\n#include \"arena.h\"\n\n...\n```\n\n# 🧮 Usage Considerations\n\n- **Lifetime Management:** Arena allocators are best suited for situations where many objects have the same lifetime and can be \ndeallocated all at once by destroying the entire arena. They are not ideal for fine-grained, individual deallocations.\n\n- **Fragmentation:** Internal fragmentation can occur if many small allocations are made, leaving small unused gaps within chunks that are too small for subsequent allocations.\nTo reduce internal fragmentation, the `ARENA_REDUCE_FRAGMENTATION` mode was introduced, which is responsible for finding free space to use within the arena chunks.\n- **Performance:** Can offer significant performance benefits over malloc/free for frequent allocations, as it reduces system call overhead and improves cache locality.\n- **Memory Overhead:** Each `arena_chunk_t` has a small overhead for its next, size, and used members.\n\n# 🧩 Contributing\nWe welcome contributions! Please follow these steps:\n\n1. Fork the repository.\n2. Create a new branch (using this [convention](https://medium.com/@abhay.pixolo/naming-conventions-for-git-branches-a-cheatsheet-8549feca2534)).\n3. Make your changes and commit them with descriptive messages.\n4. Push your changes to your fork.\n5. Create a pull request to the main repository.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frax-x%2Farena-allocator","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frax-x%2Farena-allocator","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frax-x%2Farena-allocator/lists"}