When I have a user defined type like the following:
typedef struct MyData_t {
uint16 val;
...
} MyData;
And a simple array that I want to use to store different types of structures in:
uint8 buffer[];
And I then want to create a structure pointer that uses the array to store the data of that structure:
MyData* freelist = (MyData*) buffer;
Then I get the MISRA 2012 Error:
Note 9087: cast performed between a pointer to object type and a pointer to a different object type [MISRA 2012 Rule 11.3, required]
This rule says because of possible alignment issues it is never safe to cast pointers between different types of objects. My question is: How common is it in an embedded environment for compilers to cause any issues in this case? And how could I prevent these issues when forced to keep the implementation concept (about the buffer array that stores different types of objects)?
CodePudding user response:
You can probably circumvent the error through first casting it to a void*
pointer.
That being said, it is still implementation defined behaviour and therefore goes against MISRA guidelines. You are only guaranteed validity as per the standard if you cast to void*
and back to the exact same type.
However, there may often be cases in embedded systems where this is needed, eg. to access specific memory areas. I have had some at least. In these cases you'd need to have this use signed-off by management as per MISRA.
CodePudding user response:
How common is it in an embedded environment for compilers to cause any issues in this case?
Common enough to failing to meet alignment needs. E.g. buffer[]
may exist on an odd address and access to uint16_t
needs an even one. Result: bus violation. Any casting will not help.
how could I prevent these issues
Use a union
of uint8_t[]
and struct MyData_t
.
CodePudding user response:
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.