X86: устранение сбоев выравнивания данных (иначе SIGBUS на sparc)
Как-то можно поймать ошибки выравнивания данных даже на i386? Возможно, установив специальный регистратор i386 или что-то в этом роде.
В Solaris-Sparc я получаю SIGBUS в этом случае, но на i386 все в порядке.
Окружающая среда:
- 32-разрядное приложение
- Ubuntu Karmic
- gcc/g++ v4.4.1
ИЗМЕНИТЬ:
Вот почему я спрашиваю об этом:
- наше приложение вылетает на Sol-Sparc с SIGBUS. Для отладки я попытался бы получить аналогичное поведение на нашей платформе i386.
- наша Sol-sparc-машина работает очень медленно, поэтому компиляция и отладка занимает много времени. И наша машина i386 невероятно проста (8 ядер, 32 Гб памяти).
- Даже на платформах i386 существует стоимость производительности при ошибках выравнивания данных. И поэтому я хотел бы исправить ошибки выравнивания данных, где это возможно.
Ответы
Ответ 1
Чтобы развернуть на Vokuhila-Oliba ответ, глядя на "SOF Mis-aligned указатели на x86." поток кажется, что gcc может генерировать код с неправильно выровненной памятью доступ. AFAIK у вас нет никакого контроля над этим.
Включение проверки выравнивания в gcc-компилированном коде было бы плохой идеей. Вы рискуете получить ошибки SIGBUS для хорошего кода C.
ReEdited: Извините за это
Ответ 2
Тем временем я нашел документ CPU Intel, рассматривающий этот вопрос.
См. Руководство разработчика программного обеспечения для разработчиков Intel® 64 и IA-32.
Кажется, сложно собрать все это вместе. Однако это не похоже, что это совершенно невозможно. Интересная глава - 4.10.5 Проверка выравнивания
EDIT (некоторые конденсированные материалы из упомянутого документа):
страница 5-60
Interrupt 17 Alignment Check Exception (#AC)
to enable alignment checking, the following conditions must be true:
AM flag is set(bit 18 of control regisster CR0)
AC flag is set (bit 18 of the EFLAGS)
The CPL is 3 (protected mode or virtual-8086 mode).
дополнительно - в 14.8.2.6 - упоминаются ошибки контроллера памяти. Я не знаю, является ли это одним и тем же, другими словами:
table 14-11, Encoding of MMM and CCCC Sub-Fields
Address/Command Error AC 011
Ответ 3
Я нашел очень простое решение на SOF! См. Неравномерные указатели на x86.
int main(int argc, char **argv)
{
# if defined i386
/* EDIT: enable AC check */
asm("pushf; "
"orl $(1<<18), (%esp); "
"popf;");
# endif
char d[] = "12345678"; /* yep! - causes SIGBUS even on Linux-i386 */
return 0;
}
Но я должен признаться, что не понимаю, почему назначение
char d [] = "12345678";
считается ошибочным?
EDIT:
на машине SPARC нет строки SIGBUS в строке присвоения char d [].
Ответ 4
Intel очень велика для поддержки невыложенных нагрузок. Если бы мне приходилось обнаруживать такие нагрузки на платформе Intel, я бы подумал, что мне придется изменить valgrind
для обработки неуравновешенных нагрузок как ошибок. Такая модификация не является тривиальной, но valgrind был разработан с учетом того, что пользователи могут создавать новые "инструменты". Я думаю, что простая модификация инструмента memcheck
обнаружит ваши неустановленные ссылки. И отчет об ошибках действительно очень приятный.
Ответ 5
Intel построила несвязанные переводы с самого начала - это была одна из точек продажи, когда x86 был совершенно новым. Я понимаю ваши причины для того, чтобы улавливать неприсоединенный доступ, но я не думаю, что это возможно.
Изменить: очень рад быть доказанным.
Ответ 6
Много лет спустя: если ваш gcc/clang является достаточно новым (GCC 4.9, clang 3.3?), вы можете создать свой код с помощью дезактиватора поведения undefined (-fsanitize=undefined
), чтобы получать предупреждения о несогласованных доступах на (но иметь в виду, что разные платформы имеют разные требования к выравниванию, разные компиляторы будут выбирать разные макеты и т.д.). См. https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html и https://developers.redhat.com/blog/2014/10/16/gcc-undefined-behavior-sanitizer-ubsan/ для получения более подробной информации.