Вопрос

Что означает сообщение "ошибка шины" и чем оно отличается от segfault?

Это было полезно?

Решение

Ошибки шины в настоящее время редки на x86 и возникают, когда ваш процессор обычно не может даже попытаться получить запрошенный доступ к памяти:

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

Ошибки сегментации возникают при доступе к памяти, которая не принадлежит вашему процессу, они очень распространены и обычно являются результатом:

  • использование указателя на что-то, что было освобождено.
  • использование неинициализированного, следовательно, поддельного указателя.
  • используя нулевой указатель.
  • переполнение буфера.

PS:Чтобы быть более точным, это не манипулирование самим указателем, которое вызовет проблемы, это доступ к памяти, на которую он указывает (разыменование).

Другие советы

Segfault обращается к памяти, к которой у вас нет доступа. Он доступен только для чтения, у вас нет разрешения и т. Д.

Ошибка шины при попытке доступа к памяти, которой там быть не может. Вы использовали адрес, который не имеет смысла для системы, или неправильный адрес для этой операции.

Я полагаю, что ядро вызывает SIGBUS когда приложение отображает данные рассогласование на шине данных.Я думаю что, поскольку большинство [?] современных компиляторов для большинства процессоров заполняют / выравнивают данные для программистов, проблемы с выравниванием прошлых лет (по крайней мере) смягчены, и, следовательно, никто не видит СИГБУС слишком часто в наши дни (AFAIK).

От: Здесь

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 и продолжающегося на len байт, на целые страницы, следующие за окончанием объекта, должны приводить к доставке сигнала 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 поля, я обобщил соответствующие документы чуть дальше здесь.

Вы также можете получить SIGBUS, когда по какой-то причине невозможно вставить кодовую страницу.

Один классический случай ошибки шины - это некоторые архитектуры, такие как SPARC ( по крайней мере, некоторые SPARC, возможно, это было изменено), когда вы делаете неправильный доступ. Например:

unsigned char data[6];
(unsigned int *) (data + 2) = 0xdeadf00d;

Этот фрагмент кода пытается записать 32-разрядное целочисленное значение 0xdeadf00d по адресу, который (скорее всего) не выровнен должным образом, и сгенерирует ошибку шины на архитектурах, которые «разборчивы». в этой связи. Между прочим, Intel x86 не такой архитектуры, она позволила бы доступ (хотя и выполнять его медленнее).

Это зависит от вашей операционной системы, процессора, компилятора и, возможно, других факторов.

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

-Адам

Обычно это означает неприсоединенный доступ.

Попытка получить доступ к памяти, которая физически отсутствует, также приведет к ошибке шины, но вы не увидите этого, если используете процессор с MMU и ОС, которая не глючит, потому что вы не будете иметь любую несуществующую память, сопоставленную с адресным пространством вашего процесса.

Конкретный пример ошибки шины, с которой я только что столкнулся при программировании 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;
}

В случае, если вы не помните, документы strcat добавляют второй аргумент к первому, изменяя первый аргумент (переверните аргументы, и все работает нормально). В Linux это дает ошибку сегментации (как и ожидалось), но в OS X это дает ошибку шины. Зачем? Я действительно не знаю.

Я получал ошибку шины, когда корневой каталог был на 100%.

Моя причина ошибки шины в Mac OS X заключалась в том, что я попытался выделить около 1 МБ в стеке. Это работало хорошо в одном потоке, но при использовании openMP это приводит к ошибке шины, потому что Mac OS X имеет очень ограниченный размер стека для неосновных потоков .

Чтобы добавить то, что blxtd ответил выше, ошибки шины также возникают, когда ваш процесс не может попытаться получить доступ к памяти определенной «переменной» .

for (j = 0; i < n; j++) {
                for (i =0; i < m; i++) {
                        a[n+1][j] += a[i][j];
                }
        }

Обратите внимание на непреднамеренное использование переменной 'i' в first for for loop? Вот что в этом случае вызывает ошибку шины.

Я только что обнаружил, что на процессоре ARMv7 вы можете написать некоторый код, который выдает ошибку сегментации, когда не оптимизирован, но выдает ошибку шины при компиляции с -O2 (оптимизируйте больше). Я использую кросс-компилятор gcc arm gnueabihf из Ubuntu x64.

Я согласен со всеми ответами выше. Вот мои 2 цента относительно ошибки BUS:

Ошибка BUS не должна возникать из инструкций в коде программы. Это может произойти, когда вы запускаете двоичный файл и во время выполнения двоичный файл изменяется (перезаписывается сборкой или удаляется и т. Д.).

Проверка, так ли это: Простой способ проверить, является ли это причиной, - запустить запущенные экземпляры одного и того же двоичного файла и запустить сборку. Оба запущенных экземпляра завершатся с ошибкой SIGBUS вскоре после завершения сборки и заменят двоичный файл (тот, который в данный момент запущен обоими экземплярами)

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

Типичное переполнение буфера, которое приводит к ошибке шины,

{
    char buf[255];
    sprintf(buf,"%s:%s\n", ifname, message);
}

Здесь, если размер строки в двойных кавычках (" ") больше размера буфера, это дает ошибку шины.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top