Что такое ошибка шины?

193

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

  • 4
    Я хотел бы добавить простое объяснение для обоих: ошибка сегментации означает, что вы пытаетесь получить доступ к памяти, к которой у вас нет доступа (например, это не является частью вашей программы). Однако при ошибке шины это обычно означает, что вы пытаетесь получить доступ к памяти, которой не существует (например, вы пытаетесь получить доступ к адресу в 12G, но у вас есть только 8G памяти), или если вы превысили лимит используемой памяти.
Теги:
segmentation-fault

15 ответов

175
Лучший ответ

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

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

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

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

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

  • 89
    Они не редкость; Я только на Упражнении 9 из «Как научиться трудному пути» и уже столкнулся с одним ...
  • 19
    Другая причина ошибок шины (в любом случае в Linux) - это когда операционная система не может создать резервную копию виртуальной страницы с физической памятью (например, из-за нехватки памяти или из-за огромных страниц при использовании огромной памяти страниц.) Обычно mmap (и malloc) просто зарезервируйте виртуальное адресное пространство, и ядро назначает физическую память по требованию (так называемые ошибки программных страниц). Создайте достаточно большой malloc, а затем запишите его достаточно, и вы получите ошибку шины.
Показать ещё 5 комментариев
68

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

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

9

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

От: Здесь

  • 1
    Зависит от неприятных трюков, которые вы делаете с вашим кодом. Вы можете вызвать ошибку BUS / Alignment Trap, если вы делаете что-то глупое, например, делайте указатель по математике и затем настраиваете тип для доступа к проблемному режиму (т. Е. Вы устанавливаете массив uint8_t, добавляете один, два или три к указателю массива, а затем вводите тип to short, int или long и попытайтесь получить доступ к ошибочному результату.) Системы X86 в значительной степени позволят вам сделать это, хотя и с реальным снижением производительности. НЕКОТОРЫЕ системы ARMv7 позволят вам сделать это, но большинство ARM, MIPS, Power и т. Д. Будут ворчать по этому поводу.
5

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

  • 6
    Это часто происходит, когда я обновляю .so файл во время выполнения процесса
  • 0
    Другая причина, по которой это происходит, - это попытка mmap файл размером больше /dev/shm
3

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 как:

Доступ к части undefined объекта памяти.

спецификация mmap говорит, что:

Ссылки в диапазоне адресов, начинающиеся с pa и продолжающиеся для len-байтов на целые страницы, следующие за концом объекта, должны привести к передаче сигнала SIGBUS.

И shm_open говорит, что он генерирует объекты размером 0:

Объект общей памяти имеет нулевой размер.

Итак, при *map = 0 мы касаемся конца выделенного объекта.

3

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

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

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

  • 1
    В случае, если у меня были данные [8]; Это теперь кратно 4 в 32-битной архитектуре. Итак, оно выровнено. Я все еще получу ошибку сейчас? Также, пожалуйста, объясните, это плохая идея для преобразования типов данных для указателей. Это приведет к ошибкам неправильного выравнивания на хрупкой архитектуре. Пожалуйста, опишите подробно, это поможет мне.
  • 0
    Хех. Это не столько преобразование типов, сколько преобразование типов для указателя, которое вы выполняли с помощью математики указателя. Посмотрите внимательно на код выше. Компилятор тщательно выровнял указатель dword по указателю на данные, а затем вы все испортили в компиляторе, сместив ссылку на TWO и приведя тип к очень большому объему доступа с выравниванием по dword к границе, не связанной с dword.
Показать ещё 5 комментариев
2

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

2

Конкретный пример ошибки шины, с которой я столкнулся только при программировании 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 она дает ошибку шины. Зачем? Я действительно не знаю.

  • 0
    Вероятно, защита от переполнения стека вызывает ошибку шины.
  • 1
    "foo" хранится в сегменте памяти, доступном только для чтения, поэтому запись в него невозможна. Это не защита от переполнения стека, а защита от записи в память (это дыра в безопасности, если ваша программа может переписать себя).
2

Обычно это означает, что вы не выровнены.

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

  • 2
    Мой i7, конечно, имеет MMU, но я все еще сталкивался с этой ошибкой, изучая C на OS X (передавая неинициализированный указатель на scanf ). Означает ли это, что OS X Mavericks глючит? Каково было бы поведение на не глючной ОС?
2

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

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

-Adam

1

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

0

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

0

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

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

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

-2

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

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

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

  • 1
    Хех ... если бы это было так, у вас были бы проблемы с ошибкой BUS вместо того, чтобы разбивать стек, о котором вы читали все время для Windows и других машин. Ошибки шины вызваны попыткой доступа к «памяти», к которой машина просто не может получить доступ, потому что адрес недействителен. (Отсюда и термин «ошибка BUS».) Это может быть связано с множеством сбоев, включая недопустимые выравнивания и тому подобное, если процессор не может разместить адрес на линиях шины.
-3

Это может касаться и человеческих проблем. В различных областях исследований (возможно, шире) сленговая "ошибка шины" имеет другое значение, которое, я думаю, может быть релевантным ответом. Когда есть только один человек, который знает, как сделать что-то важное для конкретного рабочего процесса, и этот человек внезапно становится недоступным (т.е. "Падает под автобус" - но, скорее всего, просто взлетает и уходит неожиданно), это называется шиной ошибка. Это так же катастрофично, как и "настоящая" ошибка шины, поскольку без знания этого человека о том, как поддерживать или даже выполнять исследовательский рабочий процесс, вся система разваливается. Быть уязвимым для ошибок шины - признак плохого управления.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню