Homepage GitHub

o1heapInit alignment issue

Hi

I am trying to setup libcanard on a STM32F429I Discovery board.
When I am initializing o1heap the function returns 0. When I debug the programm I see that the check (((size_t) base) % O1HEAP_ALIGNMENT) == 0U) fails because it evaluates to 8 instead of 0.

Here is the relevant code:

static void*  base;
static O1HeapInstance* my_allocator;

base = malloc(1024);
my_allocator = o1heapInit(base, 1024, NULL, NULL);

Am I doing something wrong here?

Thanks in advance if anyone can help me with this

Yes: you need to ensure that the pointer you pass to O1Heap is aligned at O1HEAP_ALIGNMENT, which is usually 16 bytes on a 32-bit platform.

Thanks.
I found this on stackoverflow. It looks a bit sketchy but it works for now.
Do you know a better way to do this?

It’s not sketchy though, it’s perfectly valid. Alternatively, you could use the standard aligned_alloc. Although, I would question why do you need to allocate the pool using the standard heap? It doesn’t make sense to me, but I am not aware of your requirements. Why not just pass your standard malloc/free to libcanard?

Because of these lines from canard.h

/// As explained in this documentation, the library requires a deterministic constant-time bounded-fragmentation dynamic
/// memory allocator. If your target platform does not provide a deterministic memory manager (most platforms don't),
/// it is recommended to use O1Heap (MIT licensed): https://github.com/pavel-kirienko/o1heap.

Is o1heap not necessary?

Here is a more complete example of my code:

static void* memAllocate(CanardInstance* const ins, const size_t amount)
{
    (void) ins;
    return o1heapAllocate(my_allocator, amount);
}

static void memFree(CanardInstance* const ins, void* const pointer)
{
    (void) ins;
    o1heapFree(my_allocator, pointer);
}

base = malloc(UAVCAN_MEM_SIZE+15);
base_aligned = ((uintptr_t)base+15) & ~ (uintptr_t)0x0F;
my_allocator = o1heapInit(base_aligned, UAVCAN_MEM_SIZE, NULL, NULL);

ins = canardInit(&memAllocate, &memFree);

Depends on your objectives. The recommendations given in the docs assume that the application requires a hard real-time stack, in which case you need O1Heap or something similar. Your case seems rather odd because you ended up with two heaps. What are you using the other heap for? Is your application not a real-time one? Is the standard heap reachable via malloc() managed by a real-time allocator? Maybe you just need a static buffer for O1Heap like static uint8_t[UAVCAN_MEM_SIZE]?

The example you shared looks okay sans the weird double-heap thing.

Ohhh, ok. I thought o1heap needed an already allocated memory area for its init function. I didn’t know it does the allocation itself.
Ok, next question: How do I pick a base pointer for o1heapInit() if I don’t get it from malloc?

O1Heap does need an already allocated arena. What I’m asking is why do you need to allocate it dynamically? This is the part that doesn’t make sense to me. Just make a static array and pass it over to o1heapInit.

1 Like

This is my first time doing something with memory allocation and I was doing a lot of guessing :sweat_smile:. I didn’t know that I could just pass it a static array. Makes sense though.

Thank you very much for your support!