Skip to content

Instantly share code, notes, and snippets.

@kassane
Created May 4, 2025 19:49
Show Gist options
  • Save kassane/38e7c1d92a7a27a968e44f986b14744b to your computer and use it in GitHub Desktop.
Save kassane/38e7c1d92a7a27a968e44f986b14744b to your computer and use it in GitHub Desktop.
Build and run o1heap sample
/**
License: CC0
author: Matheus C. França
requires: https://github.com/pavel-kirienko/o1heap - credits: pavel-kirienko
*/
#include <stdio.h>
#include <stdint.h>
#include <stddef.h>
#include <assert.h>
#include <o1heap.h>
// Raw arena size. The actual usable heap size will be slightly less
// because some space is used internally by the allocator (typically ~40–600 bytes).
#define RAW_BUFFER_SIZE 1024
// Static arena buffer with guaranteed alignment
static uint8_t raw_buffer[RAW_BUFFER_SIZE + O1HEAP_ALIGNMENT] __attribute__((aligned(O1HEAP_ALIGNMENT)));
int main(void) {
// Align the base address of the arena manually
uintptr_t base_addr = ((uintptr_t)raw_buffer + (O1HEAP_ALIGNMENT - 1)) & ~(uintptr_t)(O1HEAP_ALIGNMENT - 1);
void* base = (void*)base_addr;
// Initialize the heap with the aligned arena
O1HeapInstance* heap = o1heapInit(base, RAW_BUFFER_SIZE);
if (!heap) {
fprintf(stderr, "Failed to initialize O1Heap.\n");
return 1;
}
// Initial diagnostics
O1HeapDiagnostics diag = o1heapGetDiagnostics(heap);
printf("Initial heap capacity: %zu bytes\n", diag.capacity);
// Allocate two 64-byte blocks
void* p1 = o1heapAllocate(heap, 64);
assert(p1 && "First allocation of 64 bytes failed");
printf("Allocated 64 bytes at %p\n", p1);
void* p2 = o1heapAllocate(heap, 64);
assert(p2 && "Second allocation of 64 bytes failed");
printf("Allocated another 64 bytes at %p\n", p2);
// Free the first block
o1heapFree(heap, p1);
printf("Freed first block\n");
// Allocate a third block — should reuse the freed space
void* p3 = o1heapAllocate(heap, 64);
assert(p3 && "Re-allocation of 64 bytes failed");
printf("Reused 64 bytes at %p\n", p3);
// Print diagnostics
diag = o1heapGetDiagnostics(heap);
printf("Currently allocated: %zu bytes\n", diag.allocated);
printf("Peak allocated: %zu bytes\n", diag.peak_allocated);
printf("Out-of-memory events: %llu\n", (unsigned long long)diag.oom_count);
// Free remaining blocks
o1heapFree(heap, p2);
o1heapFree(heap, p3);
// Heap integrity check
assert(o1heapDoInvariantsHold(heap));
printf("Heap integrity check passed.\n");
return 0;
}
@kassane
Copy link
Author

kassane commented May 4, 2025

Output

Arch: x86-64 (zen3)
OS: Arch(Linux)

$ ./sample_heap                                                    
Initial heap capacity: 448 bytes
Allocated 64 bytes at 0x55fc6963c2c0
Allocated another 64 bytes at 0x55fc6963c340
Freed first block
Reused 64 bytes at 0x55fc6963c2c0
Currently allocated: 256 bytes
Peak allocated: 256 bytes
Out-of-memory events: 0
Heap integrity check passed.

valgrind test

$ valgrind --leak-check=full --show-leak-kinds=all -s ./sample_heap
==13240== Memcheck, a memory error detector
==13240== Copyright (C) 2002-2024, and GNU GPL'd, by Julian Seward et al.
==13240== Using Valgrind-3.25.0 and LibVEX; rerun with -h for copyright info
==13240== Command: ./sample_heap
==13240== 
Initial capacity: 448 bytes
Allocated 64 bytes at 0x40052c0
Allocated another 64 bytes at 0x4005340
Freed first block
Allocated 64 bytes at 0x40052c0
Current allocated: 256
Peak allocated: 256
OOM count: 0
Heap integrity verified after cleanup.
==13240== 
==13240== HEAP SUMMARY:
==13240==     in use at exit: 0 bytes in 0 blocks
==13240==   total heap usage: 1 allocs, 1 frees, 1,024 bytes allocated
==13240== 
==13240== All heap blocks were freed -- no leaks are possible
==13240== 
==13240== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment