linux进程rl状态,Linux程序调试--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

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

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值