Ошибка шины 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.