Bus Error问题

发布时间:2016-12-11 16:11:43 编辑:www.fx114.net 分享查询网我要评论
本篇文章主要介绍了"Bus Error问题",主要涉及到Bus Error问题方面的内容,对于Bus Error问题感兴趣的同学可以参考一下。

Bus Error究竟是指什么 一Bus Error,即总线错误。 参见wiki上介绍 http://en.wikipedia.org/wiki/Bus_error#Bus_error_example  引发原因: CPU出于性能方面的考虑,要求对数据进行访问时都必须是地址对齐的。如果发现进行的不是地址对齐的访问,就会发送SIGBUS信号给进程,使进程产生 core dump。RISC包括SPARC(一种微处理器架构)都是这种类型的芯片。x86系列CPU都支持不对齐访问,也提供了开关禁用这个机制。x86架构不要求对齐访问的时候,必定会有性能代价。例如,对int的访问应该是4字节对齐的,即地址应该是4的倍数,对short则是2字节对齐的,地址应该是2的倍数。 Bus Error也有可能是因为机器物理问题或者访问无效物理地址,但这种情况非常少见。 Linux平台上执行malloc(),如果没有足够的RAM,Linux不是让malloc()失败返回,而是向当前进程分发SIGBUS信号。         注: 对该点执怀疑态度,有机会可自行测试确认当前系统反应。 SIGBUS与SIGSEGV信号的一般区别如下: 1) SIGBUS(Bus error)意味着指针所对应的地址是有效地址,但总线不能正常使用该指针。通常是未对齐的数据访问所致。 2) SIGSEGV(Segment fault)意味着指针所对应的地址是无效地址,没有物理内存对应该地址。 二例子程序:   1 int main(){ 2 3 #if defined(__GNUC__) 4 # if defined(__i386__) 5  __asm__("pushf/norl $0x40000,(%esp)/npopf"); 6 # elif defined(__x86_64__) 7  __asm__("pushf/norl $0x40000,(%rsp)/npopf"); 8 # endif 9 #endif 10 11 short array[16]; 12 13 int * p = (int *) &array[1]; 14 *p = 1; 15 16 return 1; 17 } short类型大小为2个字节,其地址必是2的倍数。而对于int指针来说,能够使用以访问数据的地址应该是4的倍数,转化arrary[1]的地址为int *并访问,系统会发出SIGBUS信号,导致程序崩溃。     wiki上的例子: http://en.wikipedia.org/wiki/Bus_error#Bus_error_example /* This is an example of unaligned memory access, written in the C programming language with AT&T assembly syntax. */ #include <stdlib.h> int main(int argc, char **argv) {       int *iptr;       char *cptr; #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         /* malloc() always provides aligned memory */        cptr = (char *) malloc(sizeof(int) + 1);         /* Increment the pointer by one, making it misaligned */        iptr = (int *) ++cptr;         /* Dereference it as an int pointer, causing an unaligned access */        *iptr = 42;         return 0; } Compiling and running the example on a POSIX compliant OS on x86 demonstrates the error: $ gcc -ansi sigbus.c -o sigbus $ ./sigbus  Bus error $ gdb ./sigbus (gdb) r Program received signal [[SIGBUS]], Bus error. 0x080483ba in main () (gdb) x/i $pc 0x80483ba <main+54>:    mov    DWORD PTR [eax],0x2a (gdb) p/x $eax $1 = 0x804a009 (gdb) p/t $eax & (sizeof(int) - 1) $2 = 1 三,编译器和硬件平台相关性 上述已经描述,对于x86平台,默认允许非对齐访问,只不过会有性能代价。开启检测可以使用上述代码中的宏。 这段程序如果用Sun Studio编译器的话,运行就没有问题。这是因为Sun Studio默认对32位编译使用的参数是-xmemalign=8i,其中i选项设置明确指明不产生SIGBUS信号。 不过如果编译成64位程序,Sun Studio使用的-xmemalign=8s,其中s选项设置意味对这种非对齐访问产生SIGBUS信号,则仍旧会遇到这个错误。 如果坚持在SPARC上使用GCC去编译这种代码,可以如下进行: GCC有一个Type Attributes特性,例如在需人工对齐的变量后加上:__attribute__ ((aligned (4))); 其意义就是指定偏移量为4的倍数。比如: short array[10] __attribute__ ((aligned (4))); 不过这个属性只对Linker连接器可见的变量有效,也就是说对local variable无效。而且这种特性作用粒度比较大,比如这里只对第一个元素有作用,并不为数组的每个成员设置偏移量。如果一定要针对local variable或者数组的每个成员进行偏移量设置,可以使用union类型: union { short s; int i; };

上一篇:Linux设备驱动之I2C架构分析【转】
下一篇:删除的文件怎么还会恢复呢?

相关文章

关键词: Bus Error问题

相关评论