Как получить "автобусную ошибку"?

Я очень стараюсь получить ошибку шины.

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

есть ли какая-то ситуация, которая обязательно приведет к ошибке шины?

12 ответов


ошибки шины могут быть вызваны только на аппаратных платформах, которые:

  1. требуется выровненный доступ и
  2. не компенсируйте несогласованный доступ, выполнив два выровненных доступа и объединив результаты.

У вас, вероятно, нет доступа к такой системе.


это должно надежно привести к 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* ...