如何解决bus error
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何解决bus error相关的知识,希望对你有一定的参考价值。
一,Bus Error究竟是指什么Bus Error,即总线错误。
引发原因:
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
4
5
6 #if defined(__GNUC__)
7 # if defined(__i386__)
8
9 __asm__("pushf/norl $0x40000,(%esp)/npopf");
10 # elif defined(__x86_64__)
11
12 __asm__("pushf/norl $0x40000,(%rsp)/npopf");
13 # endif
14 #endif
15
16
17
18
19
20
21
22
23
24 short array[16];
25
26 int * p = (int *) &array[1];
27 *p = 1;
28
29 return 1;
30
short类型大小为2个字节,其地址必是2的倍数。而对于int指针来说,能够使用以访问数据的地址应该是4的倍数,转化arrary[1]的地址为int *并访问,系统会发出SIGBUS信号,导致程序崩溃。
wiki上的例子:
http://en.wikipedia.org/wiki/Bus_error#Bus_error_example
#include <stdlib.h>
int main( int argc, char ** argv)
int * iptr;
char * cptr;
#if defined(__GNUC__)
# if defined(__i386__)
__asm__( "pushf/n orl $0x40000,(%esp)/n popf" ) ;
# elif defined(__x86_64__)
__asm__( "pushf/n orl $0x40000,(%rsp)/n popf" ) ;
# endif
#endif
cptr = malloc( sizeof ( int ) + 1) ;
iptr = ( int * ) ++ cptr;
* iptr = 42 ;
return 0 ;
$ 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;
参考技术A bus error总线错误;
在x86+Linux上写的程序,在PC机上运行得很好。可是使用ARM的gcc进行交叉编译,再送到DaVinci目标板上运行的时候,
出现了Bus error。
出现的位置如下(其中Debug的内容是我在程序中添加的调试信息):
root@211.69.193.189:~# arm_v5t_le-gcc -g shit.c
root@211.69.193.189:~# ./a.out
Debug: malloc space for the actual data: temp_buf = 0x13118
Debug: in my_recvn()
Debug: nleft = 52
Bus error
打开调试器进行调试:
root@211.69.193.189:~# gdb a.out
GNU gdb 6.3 (MontaVista 6.3-20.0.22.0501131 2005-07-22)
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "armv5tl-montavista-linuxeabi"...Using host libthread_db library "/lib/tls/libthread_db.so.1".
(gdb) run // 运行程序
Starting program: /home/zpf/a.out
Debug: in get_program_info()
Debug: in conn_server(char *err_buf_ptr)
Debug: gonna create a socket
Debug: gonna fill in the serv_addr structure
Debug: gonna connect to a server
Debug: gonna send LIN_RST
Debug: in my_sendn()
Debug: send 4 bytes to server:
Debug: gonna receive LIN_RSP
Debug: in my_recvn()
Debug: nleft = 3
Debug: received first 3 bytes from server: 7
Debug: gonna check if 3rd byte is the package type
Debug: received package length = 55
Debug: malloc space for the actual data: temp_buf = 0x13118
Debug: in my_recvn()
Debug: nleft = 52
Program received signal SIGBUS, Bus error. // 在这里出现了错误
0x00009624 in alloc_prog_mem (detail_buf=0x13118 "\001\002",
err_buf_ptr=0xbefffc40 "") at shit.c:631
631 g_data_ptr->progtype_num = *(short *)ptr ;//这个是第631行源代码,出错的代码
(gdb) print ptr // 查看一下ptr的值
$1 = 0x13119 "\002" // 地址起始是奇数!!!
(gdb) set ptr=0x1311a // 想改一下
(gdb) continue
Continuing.
Program terminated with signal SIGBUS, Bus error.
The program no longer exists. // 可惜程序已经退出
(gdb) quit
其中,g_data_ptr->progtype_num是一个short类型的值。
把强制类型转换改为用memcpy()写值之后,再调试
root@211.69.193.189:~# gdb test
GNU gdb 6.3 (MontaVista 6.3-20.0.22.0501131 2005-07-22)
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "armv5tl-montavista-linuxeabi"...Using host libthread_db library "/lib/tls/libthread_db.so.1".
(gdb) break 626 // 把刚刚的那句强制类型转换变成内存拷贝
Breakpoint 1 at 0x9630: file test.c, line 626.
(gdb) run
Starting program: /home/zpf/test
Debug: in get_program_info()
Debug: in conn_server(char *err_buf_ptr)
Debug: gonna create a socket
Debug: gonna fill in the serv_addr structure
Debug: gonna connect to a server
Debug: gonna send LIN_RST
Debug: in my_sendn()
Debug: send 4 bytes to server:
Debug: gonna receive LIN_RSP
Debug: in my_recvn()
Debug: nleft = 3
Debug: received first 3 bytes from server: 7
Debug: gonna check if 3rd byte is the package type
Debug: received package length = 55
Debug: malloc space for the actual data: temp_buf = 0x13118
Debug: in my_recvn()
Debug: nleft = 52
Breakpoint 1, alloc_prog_mem (detail_buf=0x13118 "\001\002",
err_buf_ptr=0xbefffc40 "") at test.c:626
warning: Source file is more recent than executable.
626 memcpy(&(g_data_ptr->prog_num), ptr, 2) ; // 在这一句中断,就是把上面那句出错的源代码改成memcpy
(gdb) print ptr // 再看看ptr
$1 = 0x1311b "\003" // 还是奇数地址
(gdb) continue // 继续执行
Continuing.
Debug: sum_progtype = 2 , sum_prog = 3
Debug: gonna malloc space for progtype_ptr
Debug: gonna malloc space for prog_ptr
Debug: in mv_pkg2prog_list()
Debug: gonna set ProgramType program_type_name
Debug: ProgramType program_type_name set OK
Debug: in $ == *ptr, j = 0
Debug: g_data_ptr->progtype_ptr[j].prog_ptr = temp_prog_ptr
Debug: in @ == *ptr, ptr = 0x13126
Debug: temp_prog_ptr->format = *ptr
Debug: temp_prog_ptr->program_id = *(int *)ptr
Debug: gonna set Program program_name
Debug: Program program_name set OK
Debug: finished one loop of while
Debug: in @ == *ptr, ptr = 0x1312f
Debug: temp_prog_ptr->format = *ptr
Debug: temp_prog_ptr->program_id = *(int *)ptr
Debug: gonna set Program program_name
Debug: Program program_name set OK
Debug: finished one loop of while
Debug: gonna set ProgramType program_type_name
Debug: ProgramType program_type_name set OK
Debug: in $ == *ptr, j = 1
Debug: g_data_ptr->progtype_ptr[j].prog_ptr = temp_prog_ptr
Debug: in @ == *ptr, ptr = 0x13142
Debug: temp_prog_ptr->format = *ptr
Debug: temp_prog_ptr->program_id = *(int *)ptr
Debug: gonna set Program program_name
Debug: Program program_name set OK
Debug: finished one loop of while
program type[0]
program_type_id = 1
program_type_name = love
program_num = 2
prog_ptr = 0x131d8
program[0]
program_id = 1001
program_name = you
format = 1
program[1]
program_id = 1002
program_name = me
format = 2
program type[1]
program_type_id = 2
program_type_name = hatred
program_num = 1
prog_ptr = 0x13248
program[0]
program_id = 2005
program_name = kill
format = 5
Debug: gonna return an OK
Debug: Entering send_exit_requstion()
Debug: in conn_server(char *err_buf_ptr)
Debug: gonna create a socket
Debug: gonna fill in the serv_addr structure
Debug: gonna connect to a server
Debug: gonna send EXIT_RST
Debug: in my_sendn()
Debug: send 4 bytes to server:
Debug: in my_recvn()
Debug: nleft = 4
Debug: gonna return an OK
Program exited normally. // 执行通过了!!!!
(gdb)
总结:
问题总算找到了,就是我企图在一个奇数地址起始的地方强制类型转换得到一个short值。
在Intel系列处理器上,可以在任一奇数内存地址储存任何变量或数组,不会导致任何致命的错误影响,只是效率可能会降低。
但在DaVinci上,这一点 不行。所以必须对大于一个字节的数据类型小心谨慎,比较安全的方法是使用
内存拷贝函数memcpy(),或者使用下面的代替方法:
// 先定义一个联合体
union
short short_val ;
char short_byte[2] ;
myshort ;
// 然后,把程序中本来应该是
// g_data_ptr->progtype_num = *(short *)ptr ;
// ptr += 2 ;
// 这两句的地方换成下面五句:
myshort.short_byte[0] = *ptr ;
ptr++ ;
myshort.short_byte[1] = *ptr ;
ptr++ ;
g_data_ptr->progtype_num = myshort.short_val ;
// 当然,最简单的方法是换成下面两句:
// memcpy(&(g_data_ptr->progtype_num), ptr, 2) ;
// ptr += 2 ;
对于这个问题的进一步探讨:
在DaVinci上应该注意内存编址模式的问题。
struct
char struc_char ;
int struc_int ;
short struc_short ;
long struct_long ;
struc_val ;
在宽松模式下,尽管struc_char只有1个字节,struc_short占2个字节,但编译器可能给这两个变量分别分配了4个字节,
结果整个结构的 大小变成了16个字节,而在编译器设为紧凑模式时,则正好是11个字节。根据计算机数据总线的位数,
不同的编址模式存取数据的速度不一样。我认为在符合总 线字长的情况下,效率是最高的,因为只需进行一次总线操作。
内存编址模式会影响字节对齐方式,字节对齐操作可以解决以下两个主要的问题:
1.访存效率问题;一般的编译器要对内存进行对齐,在处理变量时,编译器会根据一定的设置将长短不同的变量的数据
长度进行对齐以加快内存处理速度。
2.强制类型转换问题:在x86上,字节不对齐的操作只会影响效率,但是在DaVinci上,可能就是一个Bus error,
因为它要求必须字节对齐。
字节对齐的准则
1.数据类型自身的对齐值:对于char型数据,其自身对齐值为1,对于short型为2,对于int,long,float,double类型,
其自身对齐值为4字节。
2.结构体的自身对齐值:其成员中自身对齐值最大的那个值。
3.指定对齐值:#pragma pack (value)时的指定对齐值value。
4.数据成员、结构体和类的有效对齐值:自身对齐值和指定对齐值中小的那个值。
对于平时定义变量,尽可能先定义长度为4的倍数的变量,然后是长度是2的变量,最后是长度为1的变量。
通过测试,GCC编译器是按照4字节对齐存放于内存的。而我还没有发现更改编址模式的参数。程序如下:
#include
int main()
struct
char struc_char ;
int struc_int ;
short struc_short ;
long struct_long ;
struc_val ;
char c_char ;
int i_int ;
short s_short ;
long l_long ;
printf("sizeof(struc_val) = %d\n", sizeof(struc_val));
printf("sizeof(c_char) = %d\n", sizeof(c_char));
printf("sizeof(i_int) = %d\n", sizeof(i_int));
printf("sizeof(s_short) = %d\n", sizeof(s_short));
printf("sizeof(l_long) = %d\n", sizeof(l_long));
printf("address of struc_val = %p\n", &struc_val);
printf("address of struc_char = %p\n", &(struc_val.struc_char));
printf("address of struc_int = %p\n", &(struc_val.struc_int));
printf("address of struc_short = %p\n", &(struc_val.struc_short));
printf("address of struct_long = %p\n", &(struc_val.struct_long));
printf("address of c_char = %p\n", &c_char);
printf("address of i_int = %p\n", &i_int);
printf("address of s_short = %p\n", &s_short);
printf("address of l_long = %p\n", &l_long);
return 0 ;
测试结果:
sizeof(struc_val) = 16
sizeof(c_char) = 1
sizeof(i_int) = 4
sizeof(s_short) = 2
sizeof(l_long) = 4
address of struc_val = 0xbf885278
address of struc_char = 0xbf885278
address of struc_int = 0xbf88527c
address of struc_short = 0xbf885280
address of struct_long = 0xbf885284
address of c_char = 0xbf885277
address of i_int = 0xbf885270
address of s_short = 0xbf88526e
address of l_long = 0xbf885268
所以对于一个32位的数据来讲,如果其没有在4字节整除的内存地址处存放,那么处理器就需要2个总线周期对其进行访问。
0x08 | byte8 | byte9 | byteA | byteB |
0x04 | byte4 | byte5 | byte6 | byte7 |
0x00 | byte0 | byte1 | byte2 | byte3 |
对 于我刚刚的那个出现Bus error的程序,假设指针ptr刚好是指向了byte3(地址是0x0),然后想进行short强制类型转换,
使用byte3,byte4来构成一个 short类型的值,由于第一次总线的数据只有byte0,byte1,byte2,byte3,取不到byte4,
这在DaVinci板子上,就是一个 Bus error了,因为没有达到边界对齐。如果ptr指的是byte2(地址0x02),就没有问题了。
因为0x02地址值是sizeof(short)的整 数倍。
最近在论坛上看到一个程序员在询问Bus Error的问题。他有一个非常简单的测试程序,将一个short数组中第二个成员变量的地址附给一个int型的指针,接着给该指针赋值,大致代码如下:
short array[10];
int * p = (int *) &array[1];
*p = 1;
运行的平台是Solaris for SPARC,使用的编译器是GCC,程序执行到指针赋值的时候的出现Bus Error出错信息,程序coredump。他觉得非常奇怪,代码在X86平台运行的很好。其实这个问题完全是由于CPU硬件不同所造成的。
Bus Error通常都是因为非对齐访问造成的。CPU在设计上为了性能上的考虑,要求待访问,操作的数据地址都要对齐。如果发现没有对齐的访问,就会向当前进程发出SIGBUS信号,使程序崩溃。RISC包括SPARC都是这种类型的芯片。而X86架构就没有这种对齐要求。所以这段代码在Solaris 10 for X86下面没有问题,当然这是有性能的代价。Bus Error也有可能是因为机器物理问题或者访问无效物理地址,但这种情况非常少见。
上面的代码正是这种非对齐访问造成的Bus Error。short是两个字节,其地址偏移量必是2的倍数。而对于int指针来说,需要偏移量地址是4的倍数的数据,所以直接用int指针来操作地址,就很有可能导致系统发出SIGBUS信号,程序崩溃。
这段程序如果用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;
参考技术B 最近在论坛上看到一个程序员在询问Bus Error的问题。他有一个非常简单的测试程序,将一个short数组中第二个成员变量的地址附给一个int型的指针,接着给该指针赋值,大致代码如下:
short array[10];
int * p = (int *) &array[1];*p = 1;
运行的平台是Solaris for SPARC,使用的编译器是GCC,程序执行到指针赋值的时候的出现Bus Error出错信息,程序coredump。他觉得非常奇怪,代码在X86平台运行的很好。其实这个问题完全是由于CPU硬件不同所造成的。
Bus Error通常都是因为非对齐访问造成的。CPU在设计上为了性能上的考虑,要求待访问,操作的数据地址都要对齐。如果发现没有对齐的访问,就会向当前进程发出SIGBUS信号,使程序崩溃。RISC包括SPARC都是这种类型的芯片。而X86架构就没有这种对齐要求。所以这段代码在Solaris 10 for X86下面没有问题,当然这是有性能的代价。Bus Error也有可能是因为机器物理问题或者访问无效物理地址,但这种情况非常少见。
上面的代码正是这种非对齐访问造成的Bus Error。short是两个字节,其地址偏移量必是2的倍数。而对于int指针来说,需要偏移量地址是4的倍数的数据,所以直接用int指针来操作地址,就很有可能导致系统发出SIGBUS信号,程序崩溃。
这段程序如果用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; 参考技术C bus error 是总线错误,这个错误一般是程序无法有效兼容当前 CPU 的工作而报错。
在x86+Linux上写的程序,在PC机上运行得很好。可是使用ARM的gcc进行交叉编译,再送到DaVinci目标板上运行的时候,出现了Bus error。
出现的位置如下(其中Debug的内容是我在程序中添加的调试信息):
root@211.69.193.189:~# arm_v5t_le-gcc -g shit.c
root@211.69.193.189:~# ./a.out
Debug: malloc space for the actual data: temp_buf = 0x13118
Debug: in my_recvn()
Debug: nleft = 52
Bus error
打开调试器进行调试:
root@211.69.193.189:~# gdb a.out
GNU gdb 6.3 (MontaVista 6.3-20.0.22.0501131 2005-07-22)
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "armv5tl-montavista-linuxeabi"...Using host libthread_db library "/lib/tls/libthread_db.so.1".
(gdb) run // 运行程序
Starting program: /home/zpf/a.out
Debug: in get_program_info()
Debug: in conn_server(char *err_buf_ptr)
Debug: gonna create a socket
Debug: gonna fill in the serv_addr structure
Debug: gonna connect to a server
Debug: gonna send LIN_RST
Debug: in my_sendn()
Debug: send 4 bytes to server:
Debug: gonna receive LIN_RSP
Debug: in my_recvn()
Debug: nleft = 3
Debug: received first 3 bytes from server: 7
Debug: gonna check if 3rd byte is the package type
Debug: received package length = 55
Debug: malloc space for the actual data: temp_buf = 0x13118
Debug: in my_recvn()
Debug: nleft = 52
Program received signal SIGBUS, Bus error. // 在这里出现了错误
0x00009624 in alloc_prog_mem (detail_buf=0x13118 "\001\002",
err_buf_ptr=0xbefffc40 "") at shit.c:631
631 g_data_ptr->progtype_num = *(short *)ptr ;
(gdb) print ptr // 查看一下ptr的值
$1 = 0x13119 "\002" // 地址起始是奇数!!!
(gdb) set ptr=0x1311a // 想改一下
(gdb) continue
Continuing.
Program terminated with signal SIGBUS, Bus error.
The program no longer exists. // 可惜程序已经退出
(gdb) quit
其中,g_data_ptr->progtype_num是一个short类型的值。
把强制类型转换改为用memcpy()写值之后,再调试
root@211.69.193.189:~# gdb test
GNU gdb 6.3 (MontaVista 6.3-20.0.22.0501131 2005-07-22)
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "armv5tl-montavista-linuxeabi"...Using host libthread_db library "/lib/tls/libthread_db.so.1".
(gdb) break 626 // 把刚刚的那句强制类型转换变成内存拷贝
Breakpoint 1 at 0x9630: file test.c, line 626.
(gdb) run
Starting program: /home/zpf/test
Debug: in get_program_info()
Debug: in conn_server(char *err_buf_ptr)
Debug: gonna create a socket
Debug: gonna fill in the serv_addr structure
Debug: gonna connect to a server
Debug: gonna send LIN_RST
Debug: in my_sendn()
Debug: send 4 bytes to server:
Debug: gonna receive LIN_RSP
Debug: in my_recvn()
Debug: nleft = 3
Debug: received first 3 bytes from server: 7
Debug: gonna check if 3rd byte is the package type
Debug: received package length = 55
Debug: malloc space for the actual data: temp_buf = 0x13118
Debug: in my_recvn()
Debug: nleft = 52
Breakpoint 1, alloc_prog_mem (detail_buf=0x13118 "\001\002",
err_buf_ptr=0xbefffc40 "") at test.c:626
warning: Source file is more recent than executable.
626 memcpy(&(g_data_ptr->prog_num), ptr, 2) ; // 在这一句中断
(gdb) print ptr // 再看看ptr
$1 = 0x1311b "\003" // 还是奇数地址
(gdb) continue // 继续执行
Continuing.
Debug: sum_progtype = 2 , sum_prog = 3
Debug: gonna malloc space for progtype_ptr
Debug: gonna malloc space for prog_ptr
Debug: in mv_pkg2prog_list()
Debug: gonna set ProgramType program_type_name
Debug: ProgramType program_type_name set OK
Debug: in $ == *ptr, j = 0
Debug: g_data_ptr->progtype_ptr[j].prog_ptr = temp_prog_ptr
Debug: in @ == *ptr, ptr = 0x13126
Debug: temp_prog_ptr->format = *ptr
Debug: temp_prog_ptr->program_id = *(int *)ptr
Debug: gonna set Program program_name
Debug: Program program_name set OK
Debug: finished one loop of while
Debug: in @ == *ptr, ptr = 0x1312f
Debug: temp_prog_ptr->format = *ptr
Debug: temp_prog_ptr->program_id = *(int *)ptr
Debug: gonna set Program program_name
Debug: Program program_name set OK
Debug: finished one loop of while
Debug: gonna set ProgramType program_type_name
Debug: ProgramType program_type_name set OK
Debug: in $ == *ptr, j = 1
Debug: g_data_ptr->progtype_ptr[j].prog_ptr = temp_prog_ptr
Debug: in @ == *ptr, ptr = 0x13142
Debug: temp_prog_ptr->format = *ptr
Debug: temp_prog_ptr->program_id = *(int *)ptr
Debug: gonna set Program program_name
Debug: Program program_name set OK
Debug: finished one loop of while
program type[0]
program_type_id = 1
program_type_name = love
program_num = 2
prog_ptr = 0x131d8
program[0]
program_id = 1001
program_name = you
format = 1
program[1]
program_id = 1002
program_name = me
format = 2
program type[1]
program_type_id = 2
program_type_name = hatred
program_num = 1
prog_ptr = 0x13248
program[0]
program_id = 2005
program_name = kill
format = 5
Debug: gonna return an OK
Debug: Entering send_exit_requstion()
Debug: in conn_server(char *err_buf_ptr)
Debug: gonna create a socket
Debug: gonna fill in the serv_addr structure
Debug: gonna connect to a server
Debug: gonna send EXIT_RST
Debug: in my_sendn()
Debug: send 4 bytes to server:
Debug: in my_recvn()
Debug: nleft = 4
Debug: gonna return an OK
Program exited normally. // 执行通过了!!!!
(gdb) 参考技术D har * p = (char*)malloc(sizeof(int)+1);
p++;
printf("%d\n", *(int*)p);
在新机器上运行是没有问题的。
只有
预先调用
__asm__("pushf\n"
"orl $0x40000, (%rsp)\n"
"popf");
把EFLAGS的AC打开才会报bus error本回答被提问者和网友采纳
如何确定“BUS-Error”的原因
【中文标题】如何确定“BUS-Error”的原因【英文标题】:How to determine the cause for "BUS-Error" 【发布时间】:2016-05-01 18:06:06 【问题描述】:我正在开发一个带有 yocto 发行版和 python 2.7.3 的 variscite 板。
我有时会收到来自 python 解释器的总线错误消息。 我的程序在错误发生前至少几个小时或几天正常运行。 但是当我得到它一次时,我尝试重新启动程序时直接得到它。 在系统再次工作之前,我必须重新启动。
我的程序只使用了一个串口、一个 USB 通信和一些 tcp 套接字。
我可以切换到另一个硬件并遇到同样的问题。
我还使用了 python 自测 python -c "from test import testall"
我得到这两个测试的错误
test_getattr (test.test_builtin.BuiltinTest) ... 错误 test_nameprep (test.test_codecs.NameprepTest) ... 错误
自检总是在
test_callback_register_double (ctypes.test.test_callbacks.SampleCallbacksTestCase) ... 分割 故障
但是当系统运行几个小时时,自测会提前停止
ctypes.macholib.dyld 总线错误
我用memtester检查了内存,好像没问题。 如何找到问题的原因?
【问题讨论】:
memtester 是个好主意,但您可能需要检查内核消息 (dmesg
)。几周前我最后一次(也是第一次)遇到“总线错误”是在运行一些 git 命令时,但它可能是任何事情,因为根本原因显然是我的硬盘驱动器死了,正如内核跟踪所显示的那样,所以我会说这也可能是你的闪光灯。
在运行 linux 的现代系统上,总线错误通常来自尝试执行未对齐的内存访问。这通常发生在 C 程序员认为他们很聪明的时候,将一些任意指针转换为大于 char
的类型,例如懒于对文件或套接字读/写缓冲区进行序列化/反序列化。您的整个程序实际上是用 Python 编写的,还是只是将 Python 用作测试框架?当您遇到总线错误时,您可以将调试器附加到进程并回溯吗?
【参考方案1】:
总线错误通常是由应用程序试图访问硬件无法物理寻址的内存引起的。在您的情况下,存在分段错误,这可能会导致取消引用错误指针或类似的东西,从而导致访问物理上不可寻址的内存地址。我会从根源开始首先导致分段错误,因为总线错误是次要症状。
【讨论】:
【参考方案2】:一年后,我找到了问题的间接原因。
我写了一个 crc16 模块,它使用:
from ctypes import c_ushort
...
value = c_ushort(crcValue >>8 ) ...
如果出现 BUS 错误,这是有问题的部分。
我不认为 c_ushort() 函数本身会导致问题,它只是表明有问题的函数。
升级系统到Linux version 3.14.38-6QP+g8740b9f (test@Yocto) (gcc version 4.9.2 (GCC) )
后问题消失
【讨论】:
以上是关于如何解决bus error的主要内容,如果未能解决你的问题,请参考以下文章
如何解决 Uncaught ReferenceError: bus is not defined? (vue.js 2)
Harmony OS | Distributed Soft Bus
Harmony OS | Distributed Soft Bus
Harmony OS | Distributed Soft Bus
getting session bus failed: //bin/dbus-launch terminated abnormally with the following error: Autola