如何获得“总线错误”?

时间:2010-01-15 04:06:25

标签: c++ bus-error

我正在努力解决总线错误。

一种方法是错位访问,我尝试了给出herehere的示例,但没有错误 - 程序执行得很好。

是否有某种情况肯定会产生总线错误?

12 个答案:

答案 0 :(得分:15)

这应该可靠地在符合POSIX的系统上产生SIGBUS

#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信号。

答案 1 :(得分:12)

只能在以下硬件平台上调用总线错误:

  1. 需要对齐访问权限,
  2. 不要通过执行两次对齐访问并组合结果来补偿未对齐的访问。
  3. 您可能无法访问此类系统。

答案 2 :(得分:7)

尝试以下方面的内容:

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

(我知道,可能不是你想要的答案,但几乎可以肯定会给你一个“总线错误”!)

答案 3 :(得分:3)

正如其他人所说,这是非常具体的平台。在我正在使用的ARM系统(没有虚拟内存)上,有大部分地址空间没有分配内存或外设。如果我读或写其中一个地址,我会收到总线错误。

如果总线上确实存在硬件问题,也可能会出现总线错误。

如果您在具有虚拟内存的平台上运行,则可能无法故意在程序中生成总线错误,除非它是设备驱动程序或其他内核模式软件。内存管理器可能会将无效的内存访问权限作为访问冲突或类似内容(甚至从未有机会访问总线)。

答案 4 :(得分:3)

使用Intel CPU的Linux上的

试试这个:

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

这里的技巧是在其中一个CPU“特殊”寄存器中设置“对齐检查”位。

另见:here

答案 5 :(得分:3)

我确信你必须使用x86机器。 除非设置了EFALAGS寄存器中的AC标志,否则X86 cpu不会产生总线错误。

试试这段代码:

#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

答案 6 :(得分:1)

另请注意,某些操作系统会报告“错误访问”以外的错误的“总线错误”。你没有在你的问题中提到你实际上试图实现的是什么。也许这样试试:

int *x = 0;
*x=1;

您链接的Wikipedia页面提到访问不存在的内存也可能导致总线错误。将一个已知无效的地址加载到指针中并将其解除,可能会更好。

答案 7 :(得分: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;
    } 

答案 8 :(得分:1)

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(核心转储)

答案 9 :(得分:0)

简单,写入不属于你的内存:

int main()
{
    char *bus_error = 0;

    *bus_error = 'X';
}

我的PowerPC Mac [OS X 10.4,双1ghz PPC7455]上的即时总线错误,不一定在您的硬件和/或操作系统上。

甚至有一个关于总线错误的wikipedia article,包括制作一个错误的程序。

答案 10 :(得分:0)

对于0x86 arch:

#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也可能出于其他原因。

答案 11 :(得分:-1)

如果您尝试访问计算机无法访问的内存,则会发生总线错误。例如,您的计算机内存的地址范围为0x00到0xFF,但您尝试访问0x0100或更大的内存元素。

实际上,您的计算机将具有比0x00到0xFF更大的范围。

回答原帖:

  

告诉我一些肯定会产生总线错误的情况。

在您的代码中,索引到超出最大内存限制范围的内存方式。我不知道...使用某种巨型十六进制值0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF索引到一个char * ...