什么是巴士错误?

“总线错误”信息是什么意思,它与段错误有什么不同?

总线错误在x86上是罕见的,当你的处理器甚至不能尝试所请求的内存访问时,通常会发生:

  • 使用处理器指令的地址不符合其alignment要求。

在访问不属于您的进程的内存时会出现分段错误,这些错误非常普遍,通常是由于:

  • 使用一个指向已经释放的东西的指针。
  • 使用未初始化的伪指针。
  • 使用空指针。
  • 溢出缓冲区。

PS:更确切地说,这不是操纵指针本身,会导致问题,它访问它指向的内存(解引用)。

段错误正在访问您不允许访问的内存。 它是只读的,你没有权限,等等…

总线错误正试图访问不可能在那里的内存。 您已经使用了一个对系统没有意义的地址,或者是对该操作的错误地址。

当应用程序在数据总线上出现数据错位时,我相信内核会引发SIGBUS。 我认为,由于大多数处理器的现代编译器为程序员填充/alignment数据,所以至less(至less)减less了alignment问题,因此最近也没有经常看到SIGBUS(AFAIK)。

来自: 这里

当代码页由于某种原因无法被分页时,您也可以获得SIGBUS。

总线错误的一个经典实例是某些架构,比如SPARC (至less某些SPARC,也许这已经改变了),就是当您进行错误alignment的访问时。 例如:

 unsigned char data[6]; (unsigned int *) (data + 2) = 0xdeadf00d; 

这段代码尝试将32位整数值0xdeadf00d写入(最有可能)未正确alignment的地址,并且在这方面会在“挑剔”的架构上产生总线错误。 顺便说一句,Intel x86 不是这样的体系结构,它将允许访问(尽pipe执行速度更慢)。

这取决于你的操作系统,CPU,编译器和其他可能的因素。

总的来说,这意味着CPU总线无法完成一个命令,或者遭遇了冲突,但这可能意味着一系列的事情,取决于环境和正在运行的代码。

-亚当

它通常意味着一个不alignment的访问。

尝试访问没有实际存在的内存也会导致总线错误,但是如果您使用的MMU和操作系统不是错误的处理器,则不会看到这一点,因为您不会有任何非存在映射到进程地址空间的内存。

在OS X上编程C时遇到的总线错误的具体示例:

 #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上它给出了一个总线错误。 为什么? 我真的不知道。

当根目录为100%时,出现总线错误。

最小的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.04testing。

POSIX 将 SIGBUS 描述为:

访问内存对象的未定义部分。

mmap规范说:

在从pa开始的地址范围内的引用以及在对象结束之后继续len字节到整个页面的引用将导致传送SIGBUS信号。

shm_open 说它会生成大小为0的对象:

共享内存对象的大小为零。

所以在*map = 0我们正在触及分配对象的末尾。

我在Mac OS X上发生总线错误的原因是我试图在堆栈上分配大约1Mb。 这在一个线程中运行良好,但是当使用openMP时,这会导致总线错误,因为Mac OS X 对于非主线程的堆栈大小非常有限。

要添加到上面blxtd的回答中,当进程无法访问特定“variables”的内存时,也会发生总线错误。

 for (j = 0; i < n; j++) { for (i =0; i < m; i++) { a[n+1][j] += a[i][j]; } } 

注意第一个“for循环”variables“i”的“ 无意中 ”使用 这就是在这种情况下导致总线错误的原因。

我刚刚发现,在ARMv7处理器上,您可以编写一些代码,在未优化时给您一个分段错误,但在使用-O2(优化更多)进行编译时会出现总线错误。 我使用gcc arm gnueabihf来自ubuntu x64的交叉编译器。

导致总线错误的典型缓冲区溢出是,

 { char buf[255]; sprintf(buf,"%s:%s\n", ifname, message); } 

如果双引号(“”)中的string的大小大于buf大小,则会出现总线错误。

这也可能是指人类的问题。 在各个研究领域(也许更广泛),俚语“巴士错误”具有不同的含义,我认为这可能是一个相关的答案。 当只有一个人知道如何做一些对某个特定工作stream程至关重要的事情,而这个人突然变得不可用时( “跌入公共汽车” – 但很可能只是意外起起落落),这就是所谓的公共汽车错误。 这与“真正的”巴士错误一样灾难性的,因为如果没有这个人如何维护甚至执行研究工作stream程的知识,整个系统就会崩溃。 容易出现公交误差是pipe理不善的一个标志。