Как получить "автобусную ошибку"?
12 ответов
ошибки шины могут быть вызваны только на аппаратных платформах, которые:
- требуется выровненный доступ и
- не компенсируйте несогласованный доступ, выполнив два выровненных доступа и объединив результаты.
У вас, вероятно, нет доступа к такой системе.
это должно надежно привести к SIGBUS
в системе, совместимой с POSIX.
#include <unistd.h>
#include <stdio.h>
#include <sys/mman.h>
int main() {
FILE *f = tmpfile();
int *m = mmap(0, 4, PROT_WRITE, MAP_PRIVATE, fileno(f), 0);
*m = 0;
return 0;
}
из одной спецификации Unix,вызов mmap:
ссылки в диапазоне адресов, начиная с па для лен байты на целые страницы после окончания объекта должны привести к доставке сигнала SIGBUS.
попробуйте что-то вроде:
#include <signal.h>
int main(void)
{
raise(SIGBUS);
return 0;
}
(Я знаю, вероятно, не тот ответ, который вы хотите, но почти наверняка получите "ошибку шины"!)
Как упоминали другие, это очень специфично для платформы. В системе ARM, с которой я работаю (у которой нет виртуальной памяти), есть большие части адресного пространства, которым не назначена память или периферия. Если я читаю или пишу один из этих адресов, я получаю ошибки шины.
вы также можете получить ошибку шины, если на самом деле есть аппаратная проблема на шине.
Если вы работаете на платформе с виртуальной памятью, вы не могли намеренно создайте ошибку шины с вашей программой, если это не драйвер устройства или другое программное обеспечение режима ядра. Недопустимый доступ к памяти, вероятно, будет заблокирован как нарушение доступа или подобное менеджеру памяти (и у него никогда не будет шанса попасть в шину).
в linux с процессором Intel попробуйте следующее:
int main(int argc, char **argv)
{
# if defined i386
/* enable alignment check (AC) */
asm("pushf; "
"orl $(1<<18), (%esp); "
"popf;");
# endif
char d[] = "12345678"; /* yep! - causes SIGBUS even on Linux-i386 */
return 0;
}
трюк здесь состоит в том, чтобы установить бит "проверки выравнивания" в одном из "специальных" регистров процессоров.
Читайте также: здесь
Я уверен, что вы должны использовать машины x86. X86 cpu не генерирует ошибку шины, если не установлен флаг AC в регистре EFALAGS.
попробуйте этот код:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
char *p;
__asm__("pushf\n"
"orl x40000, (%rsp)\n"
"popf");
/*
* malloc() always provides aligned memory.
* Do not use stack variable like a[9], depending on the compiler you use,
* a may not be aligned properly.
*/
p = malloc(sizeof(int) + 1);
memset(p, 0, sizeof(int) + 1);
/* making p unaligned */
p++;
printf("%d\n", *(int *)p);
return 0;
}
подробнее об этом можно найти в http://orchistro.tistory.com/206
также имейте в виду, что некоторые операционные системы сообщают об "ошибке шины" для ошибок, отличных от несоосного доступа. Вы не упомянули в своем вопросе, что именно вы на самом деле пытаетесь достичь. Может быть, попробуем так:
int *x = 0;
*x=1;
страница Википедии, с которой вы связались, упоминает, что доступ к несуществующей памяти также может привести к ошибке шины. Возможно, Вам повезет с загрузкой заведомо недопустимого адреса в указатель и разыменовкой этого.
Как насчет этого? непроверенный.
#include<stdio.h>
typedef struct
{
int a;
int b;
} busErr;
int main()
{
busErr err;
char * cPtr;
int *iPtr;
cPtr = (char *)&err;
cPtr++;
iPtr = (int *)cPtr;
*iPtr = 10;
}
int main(int argc, char **argv)
{
char *bus_error = new char[1];
for (int i=0; i<1000000000;i++) {
bus_error += 0xFFFFFFFFFFFFFFF;
*(bus_error + 0xFFFFFFFFFFFFFF) = 'X';
}
}
ошибка шины: 10 (ядро сбрасывается)
просто, напишите в память, которая не ваша:
int main()
{
char *bus_error = 0;
*bus_error = 'X';
}
мгновенная ошибка шины на моем PowerPC Mac [OS X 10.4, dual 1ghz PPC7455], не обязательно на вашем оборудовании и / или операционной системе.
есть даже статья в Википедии об ошибках шины, включая программу, чтобы сделать один.
для 0x86 arch:
#include <stdio.h>
int main()
{
#if defined(__GNUC__)
# if defined(__i386__)
/* Enable Alignment Checking on x86 */
__asm__("pushf\norl x40000,(%esp)\npopf");
# elif defined(__x86_64__)
/* Enable Alignment Checking on x86_64 */
__asm__("pushf\norl x40000,(%rsp)\npopf");
# endif
#endif
int b = 0;
int a = 0xffffff;
char *c = (char*)&a;
c++;
int *p = (int*)c;
*p = 10; //Bus error as memory accessed by p is not 4 or 8 byte aligned
printf ("%d\n", sizeof(a));
printf ("%x\n", *p);
printf ("%x\n", p);
printf ("%x\n", &a);
}
Примечание: Если инструкции asm удалены, код не будет генерировать ошибку SIGBUS, как предложено другими. SIGBUS может произойти и по другой причине.
ошибки шины возникают при попытке доступа к памяти, не адресуемой компьютером. Например, память вашего компьютера имеет диапазон адресов от 0x00 до 0xFF, но вы пытаетесь получить доступ к элементу памяти в 0x0100 или выше.
на самом деле ваш компьютер будет иметь гораздо больший диапазон, чем от 0x00 до 0xFF.
чтобы ответить на ваш исходный пост:
скажите мне некоторую ситуацию, которая обязательно приведет к ошибке шины.
в коде, индексировать в память вне пределов максимального объема памяти. Не знаю ... использовать какой-то гигантский шестнадцатеричное значение 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFffffff проиндексированных в тип char* ...