If you dereference freelist
then you invoke undefined behavior. Both because of possible alignment issues as well as strict aliasing. It's a bug, MISRA or no MISRA. The easiest fix is to use memcpy
instead.
How common is it in an embedded environment for compilers to cause any issues in this case?
In case of alignment, it depends on the hardware. Some architectures like MIPS are very picky with alignment, others like generic 8-bitter MCUs couldn't care less.
As for strict aliasing bugs, it was common for the gcc compiler to go haywire upon strict aliasing violations at the time it started to gain popularity in embedded systems, somewhere around the beginning of the ARM hype year 2008-2010 somewhere (gcc versions around 3.x something?). Modern gcc versions have less strict aliasing mis-optimizations. Still always compile with -fno-strict-aliasing
when using gcc, since the compiler is instable and generally dangerous to use when strict aliasing is allowed.
As for the regular embedded systems compilers, they are usually not as stupid as to abuse strict aliasing optimizations since they want to sell their compilers.
Notably, the other way around - going from struct to character pointer - is fine. MISRA C:2012 11.3 then lists the following explicit exception:
Exception
It is permitted to convert a pointer to object type into a pointer to one of the object types char, signed char or unsigned char.
EDIT
If it's ok to break a few advisory MISRA rules like casting between integers and pointers, then perhaps something like the example below could be an option. No pointer conversions, no pointer arithmetic, no strict aliasing problems. You'll have to cast the integer into a struct pointer type on the caller side, which violates advisory rules. You have to set aside an aligned chunk of data at the address of mempool_addr
with size mempool_maxsize
in your linker script.
#include <stdint.h>
#include <stddef.h>
#define mempool_maxsize 1024u
#define mempool_addr 0x10000u
static size_t mempool_size=0u;
uintptr_t static_alloc (size_t size)
{
uintptr_t result;
if(mempool_size + size > mempool_maxsize)
{
return 0;
}
if((size % _Alignof(int)) != 0)
{
size += _Alignof(int) - (size % _Alignof(int));
}
result = mempool_addr + mempool_size;
mempool_size += size;
return result;
}