Что означает сообщение об ошибке шины и чем оно отличается от сегфоута?
Что означает сообщение об ошибке шины и чем оно отличается от сегфоута?
Ответы:
В настоящее время ошибки шины встречаются редко на x86 и возникают, когда ваш процессор не может даже попытаться получить доступ к памяти, как правило:
Ошибки сегментации возникают при доступе к памяти, которая не принадлежит вашему процессу, они очень распространены и обычно являются результатом:
PS: если быть более точным, это не манипулирование самим указателем, который вызовет проблемы, это доступ к памяти, на которую он указывает (разыменование).
/var/cache
был просто полный askubuntu.com/a/915520/493379
static_cast
редактировал void *
параметр для объекта, который хранит обратный вызов (один атрибут указывает на объект, а другой - на метод). Тогда обратный вызов называется. Однако то, что было передано как void *
нечто совершенно иное, и, следовательно, вызов метода вызвал ошибку шины.
Segfault обращается к памяти, к которой у вас нет доступа. Это только для чтения, у вас нет разрешения и т.д ...
Ошибка шины пытается получить доступ к памяти, которая не может быть там. Вы использовали адрес, который не имеет смысла для системы, или неправильный адрес для этой операции.
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
полями, я обобщил связанные документы немного дальше здесь .
Я полагаю, что ядро вызывает SIGBUS, когда приложение демонстрирует смещение данных на шине данных. Я думаю, что, поскольку большинство [?] Современных компиляторов для большинства процессоров дополняют / выравнивают данные для программистов, проблемы выравнивания в прошлом (по крайней мере) смягчаются, и, следовательно, в наши дни SIGBUS не видят слишком часто (AFAIK).
От: Здесь
Вы также можете получить SIGBUS, если по какой-то причине невозможно вставить кодовую страницу.
mmap
создать файл, размер которого больше/dev/shm
Один классический случай ошибки шины возникает в некоторых архитектурах, таких как SPARC (по крайней мере, некоторые SPARC, возможно, это было изменено), когда вы делаете неправильный доступ. Например:
unsigned char data[6];
(unsigned int *) (data + 2) = 0xdeadf00d;
Этот фрагмент кода пытается записать 32-разрядное целочисленное значение 0xdeadf00d
в адрес, который (скорее всего) не выровнен должным образом, и сгенерирует ошибку шины на архитектурах, которые «разборчивы» в этом отношении. Intel x86, кстати, не такая архитектура, она позволила бы доступ (хотя и выполнял его медленнее).
Конкретный пример ошибки шины, с которой я только что столкнулся при программировании 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 это дает ошибку шины. Зачем? Я действительно не знаю.
"foo"
хранится в сегменте памяти, доступном только для чтения, поэтому запись в него невозможна. Это не защита от переполнения стека, а защита от записи в память (это дыра в безопасности, если ваша программа может переписать себя).
Это зависит от вашей ОС, процессора, компилятора и, возможно, других факторов.
В общем, это означает, что шина ЦП не смогла выполнить команду или столкнулась с конфликтом, но это может означать целый ряд вещей, зависящих от среды и выполняемого кода.
-Адам
Обычно это означает неприсоединенный доступ.
Попытка получить доступ к памяти, которая физически отсутствует, также приведет к ошибке шины, но вы не увидите этого, если используете процессор с MMU и операционную систему, которая не глючит, потому что у вас не будет никаких -существующая память сопоставлена с адресным пространством вашего процесса.
scanf
). Означает ли это, что OS X Mavericks глючит? Каково было бы поведение на не глючной ОС?
Причиной ошибки шины в Mac OS X было то, что я попытался выделить около 1 МБ в стеке. Это хорошо работало в одном потоке, но при использовании openMP это приводит к ошибке шины, потому что Mac OS X имеет очень ограниченный размер стека для неосновных потоков .
Я согласен со всеми ответами выше. Вот мои 2 цента относительно ошибки шины:
Ошибка BUS не должна возникать из инструкций в коде программы. Это может произойти, когда вы запускаете двоичный файл и во время выполнения двоичный файл изменяется (перезаписывается сборкой или удаляется и т. Д.).
Проверка, так ли это:
Простой способ проверить, является ли это причиной, - запустить запущенные экземпляры одного и того же двоичного файла и запустить сборку. Оба запущенных экземпляра вылетят с SIGBUS
ошибкой вскоре после завершения сборки и заменят двоичный файл (тот, который в данный момент запущен обоими экземплярами)
Основная причина: это происходит потому, что ОС меняет страницы памяти, и в некоторых случаях двоичный файл может загружаться не полностью в память, и эти сбои происходят, когда ОС пытается извлечь следующую страницу из того же двоичного файла, но двоичный файл изменился с момента последнего прочитай это.
Чтобы добавить к ответу blxtd выше, также возникают ошибки шины, когда ваш процесс не может попытаться получить доступ к памяти определенной «переменной» .
for (j = 0; i < n; j++) {
for (i =0; i < m; i++) {
a[n+1][j] += a[i][j];
}
}
Заметили « непреднамеренное » использование переменной «i» в первом «цикле for»? Вот что в этом случае вызывает ошибку шины.
Я только что обнаружил, что на процессоре ARMv7 вы можете написать некоторый код, который выдает ошибку сегментации в неоптимизированном состоянии, но при компиляции с -O2 выдает ошибку шины (оптимизируйте больше).
Я использую кросс-компилятор GCC ARM gnueabihf из Ubuntu 64 бит.
Типичное переполнение буфера, которое приводит к ошибке шины,
{
char buf[255];
sprintf(buf,"%s:%s\n", ifname, message);
}
Здесь, если размер строки в двойных кавычках ("") больше размера буфера, это дает ошибку шины.