Ошибка шины C++ в архитектуре SPARC

Я хотел бы понять, почему я получаю ошибку шины с этим кодом.

int main()
{
int p=34;
int *pp= (int *) ((char *)&p+1);
cout<<*pp<<"\n";
return 0;
}

2 ответа

Решение

Это без сомнения будет проблемой выравнивания. На многих архитектурах определенные типы должны быть правильно выровнены, например, 4-байтовые целые должны начинаться с 4-байтовой границы.

Если вы обращаетесь к несогласованным данным, некоторые архитектуры не будут беспокоиться, другие будут работать медленнее, а другие (например, в этом случае) попадут в кричащую кучу.

Когда вы создаете целое число p, он будет правильно выровнен по стеку по адресу, который является правильным кратным.

Переместив этот адрес вверх на байт, и разыменовав его как intвызываешь SIGBUS,

Эта ссылка в Oracle показывает требования к выравниванию. Короче:

  • короткие целые числа выровнены по 16-битным границам.
  • целые числа типа int выровнены по 32-битным границам.
  • длинные целые числа выровнены по 64-битным границам для систем SPARC.
  • длинные длинные целые числа выровнены по 64-битным границам.

16-разрядные величины должны храниться при 16-разрядном или 2-байтовом выравнивании и 32-разрядные (4 байта) по адресам, кратным 4.

Многие процессоры поддерживают нелицензированный доступ, но это требует дополнительных микросхем в микросхеме и дополнительного времени выполнения для запуска дополнительных циклов шины памяти для выбора нечетных байтов. Это особенно распространенная философия RISC-процессоров, согласно которой компиляторы и программисты должны проявлять большую осторожность при аккуратном размещении данных для повышения скорости и упрощения схем, что является приемлемым компромиссом.

Кстати, маловероятно, что такой низкий адрес в любом случае был бы в действительной памяти. Но ваш пример иллюстрирует, что исключение выравнивания имеет приоритет над исключением SEGFAULT.

Другие вопросы по тегам