Can someone provide an example were casting a pointer from one type to another fails due to mis-alignment?
In the comments to this answer, bothie states that doing something like
char * foo = ...;
int bar = *(int *)foo;
might lead to errors even on x86 if alignment-checking is enabled.
I tried to produce an error condition after setting the alignment-check flag via set $ps |= (1<<18)
in GDB, but nothing happened.
What does a working (ie non-working ;)) example look like?
None of the code snippets from the answers fail on my system - I'll try it with a different compiler version and on a different pc later.
Btw, my own test code looked like this (now also using asm to set AC
flag and unaligned read and write):
#include <assert.h>
int main(void)
{
#ifndef NOASM
__asm__(
"pushf\n"
"orl $(1<<18),(%esp)\n"
"popf\n"
);
#endif
volatile unsigned char foo[] = { 1, 2, 3, 4, 5, 6 };
volatile unsigned int bar = 0;
bar = *(int *)(foo + 1);
assert(bar == 0x05040302);
bar = *(int *)(foo + 2);
assert(bar == 0x06050403);
*(int *)(foo + 1) = 0xf1f2f3f4;
assert(foo[1] == 0xf4 && foo[2] == 0xf3 && foo[3] == 0xf2 &&
foo[4] == 0xf1);
return 0;
}
The assertion passes without problems, even though the generated code definitely contains the unaligned access mov -0x17(%ebp), %edx
and movl $0xf1f2f3f4,-0x17(%ebp)
.
So will setting AC
trigger a SIGBUS
or not? I couldn't get it to work on my Intel dual core laptop under Windows XP with none of the GCC versions I tested (MinGW-3.4.5, MinGW-4.3.0, Cygwin-3.4.4), whereas codelogic and Jonathan Leffler mentioned failures on x86...