Может ли кто-нибудь представить пример, что приведение указателя от одного типа к другому происходит из-за неправильного выравнивания?
В комментариях к этому ответу, обе страны заявляют, что делают что-то вроде
char * foo = ...;
int bar = *(int *)foo;
может привести к ошибкам даже на x86, если включена проверка выравнивания.
Я попытался создать условие ошибки после установки флажка выравнивания через set $ps |= (1<<18)
в GDB, но ничего не произошло.
Как выглядит рабочий (т.е. нерабочий;)) пример?
Ни один из фрагментов кода из ответов не сработает в моей системе - я попробую его с другой версией компилятора и на другом ПК позже.
Btw, мой собственный тестовый код выглядел так (теперь также используйте asm для установки флага AC
и невыровненного чтения и записи):
#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;
}
Утверждение проходит без проблем, даже если сгенерированный код определенно содержит неравномерный доступ mov -0x17(%ebp), %edx
и movl $0xf1f2f3f4,-0x17(%ebp)
.
Таким образом, установка AC
вызывает a SIGBUS
или нет? Я не мог заставить его работать на моем двухъядерном ноутбуке Intel под Windows XP, и ни одна из версий GCC, которые я тестировал (MinGW-3.4.5, MinGW-4.3.0, Cygwin-3.4.4), в то время как кодологические и Джонатан Леффлер упомянутые сбои на x86...