Всегда ли невыровненный доступ к памяти вызывает ошибки шины?
В соответствии с ошибкой сегментации страницы в Википедии ошибка шины может быть вызвана неравномерным доступом к памяти. В статье приведен пример того, как вызвать ошибку шины. В этом примере мы должны включить проверку выравнивания, чтобы увидеть ошибку шины. Что если мы отключим такую проверку выравнивания?
Программа, кажется, работает правильно. У меня часто есть доступ к невыровненной памяти программы, и она используется довольно многими людьми, но никто не сообщает мне об ошибках шины или других странных результатах. Если мы отключим проверку выравнивания, каков побочный эффект невыровненной памяти?
Платформы: я работаю на x86 / x86-64. Я также попробовал свою программу, скомпилировав ее с помощью "gcc -arch ppc" на Mac, и она работает правильно.
3 ответа
Это может быть значительно медленнее для доступа к невыровненной памяти (как в несколько раз медленнее).
Не все платформы поддерживают даже выравниваемый доступ - например, x86 и x64, но ia64 (Itanium) - нет.
Компилятор может эмулировать доступ без выравнивания (VC++ делает это для указателей, объявленных как
__unaligned
на ia64, например) - путем вставки дополнительных проверок для обнаружения невыровненного регистра и загрузки / сохранения частей объекта, которые охватывают границу выравнивания по отдельности. Это даже медленнее, чем доступ без выравнивания на платформах, которые изначально поддерживают его.
Это очень сильно зависит от архитектуры чипа. x86 и POWER очень снисходительны, Sparc, Itanium и VAX создают разные исключения.
Рассмотрим следующий пример, который я только что протестировал на ARM9:
//Addresses 0 1 2 3 4 5 6 7 8 9
U8 u8Temp[10] = {0x11,0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0x00};
U32 u32Var;
u32Var = *((U32*)(u16Temp+1)); // Let's read four bytes starting from 0x22
// You would expect that here u32Var will have a value of 0x55443322 (assuming we have little endian)
// But in reallity u32Var will be 0x11443322!
// This is because we are accessing address which %4 is not 0.