Как получить «ошибку шины»? - PullRequest
15 голосов
/ 15 января 2010

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

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

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

Ответы [ 12 ]

15 голосов
/ 15 января 2010

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

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

12 голосов
/ 15 января 2010

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

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

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

7 голосов
/ 15 января 2010

Попробуйте что-нибудь вроде:

#include <signal.h>
int main(void)
{
    raise(SIGBUS);
    return 0;
}

(Я знаю, вероятно, не тот ответ, который вам нужен, но почти наверняка вы получите «ошибку шины»!)

3 голосов
/ 07 декабря 2011

Я уверен, что вы должны использовать машины x86. Процессор X86 не создает ошибку шины, если не установлен флаг AC в регистре EFALAGS.

Попробуйте этот код:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(void)
{
    char *p;

    __asm__("pushf\n"
            "orl $0x40000, (%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

3 голосов
/ 17 февраля 2010

в 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;
}

Хитрость в том, чтобы установить бит «проверки выравнивания» в одном из «специальных» регистров ЦП.

см. Также: здесь

3 голосов
/ 15 января 2010

Как уже упоминали другие, это очень зависит от платформы. В системе ARM, с которой я работаю (у которой нет виртуальной памяти), есть большие части адресного пространства, которым не назначена память или периферийные устройства. Если я читаю или пишу один из этих адресов, я получаю ошибку шины.

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

Если вы работаете на платформе с виртуальной памятью, вы не сможете преднамеренно генерировать ошибку шины с вашей программой, если это не драйвер устройства или другое программное обеспечение режима ядра. Недопустимый доступ к памяти, вероятно, будет воспринят диспетчером памяти как нарушение прав доступа или подобное ему (и у него даже не будет возможности подключиться к шине).

1 голос
/ 22 марта 2013
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 (ядро сброшено)

1 голос
/ 15 января 2010

Как насчет этого? тестировалась.

  #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;
    } 
1 голос
/ 15 января 2010

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

int *x = 0;
*x=1;

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

0 голосов
/ 18 апреля 2018

Для арки 0x86:

#include <stdio.h>

int main()
{
#if defined(__GNUC__)
# if defined(__i386__)
    /* Enable Alignment Checking on x86 */
    __asm__("pushf\norl $0x40000,(%esp)\npopf");
# elif defined(__x86_64__)
    /* Enable Alignment Checking on x86_64 */
    __asm__("pushf\norl $0x40000,(%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 может возникнуть и по другой причине.

...