Что такое ошибка шины?
Что означает сообщение "ошибка шины" и как оно отличается от segfault?
Ответы
Ответ 1
Ошибки шины в настоящее время редки на x86 и происходят, когда ваш процессор не может даже попытаться запросить доступ к памяти, как правило:
- с использованием инструкции процессора с адресом, который не удовлетворяет его требованиям к выравниванию.
При доступе к памяти, которая не принадлежит вашему процессу, возникают сбои сегментации, они очень распространены и обычно являются результатом:
- с помощью указателя на то, что было освобождено.
- используя неинициализированный, следовательно, фиктивный указатель.
- с использованием нулевого указателя.
- переполнение буфера.
PS: Чтобы быть более точным, это не манипулирует самим указателем, который вызовет проблемы, он обращается к памяти, на которую он указывает (разыменование).
Ответ 2
Segfault получает доступ к памяти, к которой у вас нет доступа. Это только для чтения, у вас нет разрешения и т.д.
Ошибка шины пытается получить доступ к памяти, которая не может быть там. Вы использовали адрес, который не имеет смысла для системы, или неправильный адрес для этой операции.
Ответ 3
Я считаю, что ядро поднимает SIGBUS когда приложение показывает данные несоосность на шине данных. я думаю что, поскольку большинство [?] современных компиляторов для большинства процессоров накладка/выравнивание данные для программистов, проблемы с выравниванием (по крайней мере) смягчается, и, следовательно, никто не видит SIGBUS слишком часто в эти дни (AFAIK).
От: Здесь
Ответ 4
mmap
минимальный пример POSIX 7
"Ошибка шины" возникает, когда ядро отправляет SIGBUS
процессу.
Минимальный пример, который производит его, потому что ftruncate
был забыт:
#include <fcntl.h> /* O_ constants */
#include <unistd.h> /* ftruncate */
#include <sys/mman.h> /* mmap */
int main() {
int fd;
int *map;
int size = sizeof(int);
char *name = "/a";
shm_unlink(name);
fd = shm_open(name, O_RDWR | O_CREAT, (mode_t)0600);
/* THIS is the cause of the problem. */
/*ftruncate(fd, size);*/
map = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
/* This is what generates the SIGBUS. */
*map = 0;
}
Запустить с помощью:
gcc -std=c99 main.c -lrt
./a.out
Проверено в Ubuntu 14.04.
POSIX описывает SIGBUS
как:
Доступ к неопределенной части объекта памяти.
спецификация mmap гласит:
Ссылки в пределах диапазона адресов, начинающиеся с pa и продолжающиеся для длинных байтов, на целые страницы после конца объекта должны привести к доставке сигнала SIGBUS.
И shm_open
говорит, что он генерирует объекты размером 0:
Объект общей памяти имеет нулевой размер.
Поэтому в *map = 0
мы касаемся конца выделенного объекта.
Нераспределенный доступ к памяти стека в ARMv8 aarch64
Об этом упоминалось в: Что такое ошибка шины? для SPARC, но здесь я приведу более воспроизводимый пример.
Все, что вам нужно, это отдельная программа aarch64:
.global _start
_start:
asm_main_after_prologue:
/* misalign the stack out of 16-bit boundary */
add sp, sp, #-4
/* access the stack */
ldr w0, [sp]
/* exit syscall in case SIGBUS does not happen */
mov x0, 0
mov x8, 93
svc 0
Затем эта программа вызывает SIGBUS на Ubuntu 18.04 aarch64, ядре Linux 4.15.0 на сервере ThunderX2.
К сожалению, я не могу воспроизвести его в пользовательском режиме QEMU v4.0.0, я не уверен почему.
Ошибка, по-видимому, является необязательной и контролируется полями SCTLR_ELx.SA
и SCTLR_EL1.SA0
, здесь я кратко изложил соответствующие документы a bit further here.
Ответ 5
Вы также можете получить SIGBUS, когда по какой-либо причине кодовая страница не может быть выгружена.
Ответ 6
Один классический пример ошибки шины относится к некоторым архитектурным решениям, таким как SPARC (по крайней мере, некоторые SPARC, возможно, это был изменен), это когда вы выполняете неверный доступ. Например:
unsigned char data[6];
(unsigned int *) (data + 2) = 0xdeadf00d;
Этот фрагмент пытается записать 32-битное целочисленное значение 0xdeadf00d
на адрес, который (скорее всего) не был правильно выровнен, и будет генерировать ошибку шины на архитектурах, которые являются "придирчивыми" в этом отношении. Intel x86 - это, кстати, не такая архитектура, что позволит получить доступ (хотя и выполнить его медленнее).
Ответ 7
Конкретный пример ошибки шины, с которой я столкнулся только при программировании C на OS X:
#include <string.h>
#include <stdio.h>
int main(void)
{
char buffer[120];
fgets(buffer, sizeof buffer, stdin);
strcat("foo", buffer);
return 0;
}
Если вы не помните, что docs strcat
добавляет второй аргумент к первому, изменив первый аргумент (переверните аргументы и он отлично работает). В linux это дает ошибку сегментации (как и ожидалось), но в OS X она дает ошибку шины. Зачем? Я действительно не знаю.
Ответ 8
Это зависит от вашей ОС, процессора, компилятора и, возможно, от других факторов.
В общем случае это означает, что CPU-шина не может выполнить команду или возникла конфликт, но это может означать целый ряд вещей в зависимости от среды и выполняемого кода.
-Adam
Ответ 9
Обычно это означает, что вы не выровнены.
Попытка доступа к памяти, которая физически не присутствует, также приведет к ошибке шины, но вы не увидите этого, если используете процессор с MMU и операционную систему, которая не глючит, потому что вы не будете иметь любую несуществующую память, отображаемую в адресное пространство вашего процесса.
Ответ 10
Я получал ошибку шины, когда корневой каталог был на 100%.
Ответ 11
Моя причина ошибки шины в Mac OS X заключалась в том, что я попытался выделить около 1 Мб в стеке. Это хорошо работает в одном потоке, но при использовании openMP эти диски приводят к ошибке шины, поскольку Mac OS X имеет очень ограниченный размер стека для не основных потоков.
Ответ 12
Чтобы добавить к ответу blxtd выше, также возникают ошибки шины, когда ваш процесс не может получить доступ к памяти определенной "переменной".
for (j = 0; i < n; j++) {
for (i =0; i < m; i++) {
a[n+1][j] += a[i][j];
}
}
Обратите внимание на непреднамеренное использование переменной "i" в первом "цикле for"? Что в этом случае вызывает ошибку шины? ,
Ответ 13
Я просто обнаружил, что на ARMv7-процессоре вы можете написать код, который дает вам ошибку сегментации при неоптимизации, но дает ошибку шины при компиляции с -O2 (оптимизируйте больше).
Я использую gcc arm gnueabihf кросс-компилятор от ubuntu x64.
Ответ 14
Я согласен со всеми ответами выше. Вот мои 2 цента относительно ошибки шины:
Ошибка шины не должна возникать из инструкций в программном коде. Это может произойти, когда вы запускаете двоичный файл и во время выполнения двоичный файл изменяется (перезаписывается сборкой или удаляется и т.д.).
Проверка, так ли это: Простой способ проверить, является ли это причиной, - запустить запущенные экземпляры одного и того же двоичного файла и запустить сборку. Оба запущенных экземпляра SIGBUS
ошибкой SIGBUS
вскоре после завершения сборки и заменят двоичный файл (тот, который в данный момент запущен обоими экземплярами)
Основная причина: это потому, что ОС меняет страницы памяти, а в некоторых случаях весь двоичный файл может находиться в памяти, и эти сбои происходят, когда ОС пытается извлечь следующую страницу из того же двоичного файла, но двоичный файл изменился с момента последнего чтения Это.
Ответ 15
Типичное переполнение буфера, которое приводит к ошибке шины,
{
char buf[255];
sprintf(buf,"%s:%s\n", ifname, message);
}
Здесь, если размер строки в двойных кавычках ("") больше, чем размер buf, он выдает ошибку шины.
Ответ 16
Это может касаться и человеческих проблем. В различных областях исследований (возможно, шире) сленговая "ошибка шины" имеет другое значение, которое, я думаю, может быть релевантным ответом. Когда есть только один человек, который знает, как сделать что-то важное для конкретного рабочего процесса, и этот человек внезапно становится недоступным (т.е. "Падает под автобус" - но, скорее всего, просто взлетает и уходит неожиданно), это называется шиной ошибка. Это так же катастрофично, как и "настоящая" ошибка шины, поскольку без знания этого человека о том, как поддерживать или даже выполнять исследовательский рабочий процесс, вся система разваливается. Быть уязвимым для ошибок шины - признак плохого управления.