I have an dynamically defined array of unsigned 8 bit integers:
const uint8_t *data;
This contains a bytestream, and is reinterpreted as various data types. I can reinterpret a position n in this data stream as a fundamental type type by:
type value = *((type*) &data[n]);
This works fine for all data types using the Visual Studio Compiler under Windows, however when compiling under Linux using gcc, this creates a SIGBUS error when type is a float (the dereferenced location is within the range of the data array). Further investigation shows that it is the pointer dereferencing that is causing this error. I have solved this by using memcpy, but would like to know why this causes a problem in the first place seeing as the address that is referenced is valid. Would a reinterpret_cast be more suitable, and if so, why?
EDIT:
I did not mention that the Linux system has an ARM architecture. @MSalters has pointed out below that there may be more stringent pointer alignment requirements for difference configurations. A short research shows that while the above is valid on x86 architectures (although not allowed by C / C++ standards), unaligned pointer dereferencing on ARM will cause a bus error.
The cast is indeed the problem. It's already a reinterpret_cast, even though you used the old C syntax. But the cast is only allowed when &data[n] actually is a valid float*. SIGBUS means it isn't. The address may be a valid char* address, but that doesn't mean it's a valid float* address. In particular, float* may have more stringent alignment requirements.
As MSalters mentions in this thread, the alignment requirement of the destination type of the cast is stronger than that of your source type, which causes SIGBUS on CPUs that do not handle unaligned access.
The way to deal with that is memcpy:
const uint8_t *data = ...;
type value;
memcpy(&value, data, sizeof value);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With