免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 12531 | 回复: 2
打印 上一主题 下一主题

Program received signal SIGBUS, Bus error.帮忙阿 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2006-09-13 16:48 |只看该作者 |倒序浏览
总是出现这个错误。奇怪的是,要是先用print 一下htons()函数的话,就能够往下执行。什么原因呢?

[Switching to Thread 8192 (LWP 32541)]

Breakpoint 1, SYSCMNinitsync (seq_no=0, wait=0 '\0', time_out=0) at syscmn_initsync.c:76
76          if(ret >= 0){
(gdb) mkdir: ディレクトリ `/tmp/bws/' を作成できません: ファイルが存在します
n
77              ret = -1;
(gdb)
80              memset(&waittime, 0, sizeof(struct timespec));
(gdb) mkdir: ディレクトリ `/tmp/bws/socket/' を作成できません: ファイルが存在します

81              waittime.tv_nsec = GKSYS_DELAY_TIME * 1000 * 1000; /* 100ms */
(gdb)
addr.sunpath is /tmp/bws/socket/DBSRV-rcv
82              while(loop == 1){
(gdb)
Successfully bind! at Server in UNIX Domain.
Local-Socket Create Success. /tmp/bws/socket/DBSRV-rcv

84                  ret = msync((void *)mapaddr, GKSYS_INIFILE_SIZE, MS_ASYNC);
(gdb)
87                  if(seq_no <= htons(*((unsigned short *)((void *)mapaddr)))){
(gdb)

Program received signal SIGBUS, Bus error.

0x08059aef in SYSCMNinitsync (seq_no=0, wait=0 '\0', time_out=0) at syscmn_initsync.c:87
87                  if(seq_no <= htons(*((unsigned short *)((void *)mapaddr)))){
(gdb)

论坛徽章:
0
2 [报告]
发表于 2006-09-13 16:55 |只看该作者
记得在sparc机器上,如果数据没有对齐的话,会产生SIGBUS总线错误,你用的是什么机器。

论坛徽章:
0
3 [报告]
发表于 2006-09-13 17:32 |只看该作者
2.0 理解SIGBUS与SIGSEGV

Q: SIGSEGV我能理解,但有时碰上SIGBUS,这该如何理解。

A: nkwht@SMTH

nkwht用Google获取这样一些知识。有多种可能导致SIGBUS信号:

1) 硬件故障,不用说,程序员最常碰上的肯定不是这种情形。

2) Linux平台上执行malloc(),如果没有足够的RAM,Linux不是让malloc()失败返回,
   而是向当前进程分发SIGBUS信号。

   注: 对该点执怀疑态度,有机会可自行测试确认当前系统反应。

3) 某些架构上访问数据时有对齐的要求,比如只能从4字节边界上读取一个4字节的
   数据类型。IA-32架构没有硬性要求对齐,尽管未对齐的访问降低执行效率。另外
   一些架构,比如SPARC、m68k,要求对齐访问,否则向当前进程分发SIGBUS信号。

SIGBUS与SIGSEGV信号一样,可以正常捕获。SIGBUS的缺省行为是终止当前进程并产
生core dump。

A: Marc Rochkind <rochkind@basepath.com>

SIGBUS与SIGSEGV信号的一般区别如下:

1) SIGBUS(Bus error)意味着指针所对应的地址是有效地址,但总线不能正常使用该
   指针。通常是未对齐的数据访问所致。

2) SIGSEGV(Segment fault)意味着指针所对应的地址是无效地址,没有物理内存对
   应该地址。

A: scz <scz@nsfocus.com> 2002-11-20

参"2.4 如何编程获取栈底地址"中如何捕获SIGBUS与SIGSEGV信号,并利用sigsetjmp、
siglongjmp重获控制权。

测试表明,在x86/Linux、x86/Solaris、SPARC/Solaris平台上,越过栈底的地址访
问导致SIGSEGV信号。在x86/FreeBSD、x86/NetBSD、x86/OpenBSD平台上,越过栈底
的地址访问导致SIGBUS信号,而不是SIGSEGV信号。

下面举例解释一下,什么叫未对齐的数据访问。

--------------------------------------------------------------------------
/*
* Test: SPARC/Solaris 8 64-bit kernel mode
* gcc -Wall -pipe -g -o bus bus.c
*/
#include <stdio.h>
#include <stdlib.h>

int main ( int argc, char * argv[] )
{
    unsigned int        i = 0x12345678;
    unsigned short int *q = NULL;
    unsigned char      *p = ( unsigned char * )&i;

    *p = 0x00;
    q  = ( unsigned short int * )( p + 1 );
    *q = 0x0000;
    return( EXIT_SUCCESS );
}  /* end of main */
--------------------------------------------------------------------------

$ ./bus
总线错误 (core dumped)
$ gdb ./bus core
GNU gdb 5.0
#0  0x1084c in main (argc=1, argv=0xffbefc54) at bus.c:16
16          *q = 0x0000;
(gdb) disas main
Dump of assembler code for function main:
0x10810 <main>   :      save  %sp, -128, %sp
0x10814 <main+4> :      st  %i0, [ %fp + 0x44 ]
0x10818 <main+8> :      st  %i1, [ %fp + 0x48 ]
0x1081c <main+12>:      sethi  %hi(0x12345400), %o1
0x10820 <main+16>:      or  %o1, 0x278, %o0     ! 0x12345678
0x10824 <main+20>:      st  %o0, [ %fp + -20 ]
0x10828 <main+24>:      clr  [ %fp + -24 ]
0x1082c <main+28>:      add  %fp, -20, %o0
0x10830 <main+32>:      st  %o0, [ %fp + -28 ]
0x10834 <main+36>:      ld  [ %fp + -28 ], %o0
0x10838 <main+40>:      clrb  [ %o0 ]
0x1083c <main+44>:      ld  [ %fp + -28 ], %o0
0x10840 <main+48>:      add  %o0, 1, %o1
0x10844 <main+52>:      st  %o1, [ %fp + -24 ]
0x10848 <main+56>:      ld  [ %fp + -24 ], %o0
0x1084c <main+60>:      clrh  [ %o0 ]
0x10850 <main+64>:      clr  %i0
0x10854 <main+68>:      b  0x1085c <main+76>
0x10858 <main+72>:      nop
0x1085c <main+76>:      ret
0x10860 <main+80>:      restore
End of assembler dump.
(gdb) i r pc
pc             0x1084c  67660
(gdb) i r o0
o0             0xffbefbdd       -4260899
(gdb) x/3bx 0xffbefbdd
0xffbefbdd:     0x34    0x56    0x78
(gdb)

从C语言来说,执行"*q = 0x0000;"时导致SIGBUS了。从汇编指令来说,执行"clrh [%o0]"
时导致SIGBUS了,寄存器%o0值为0xffbefbdd,这个地址未对齐在双字节边界上。

注意,gcc编译时并未指定-O<n>进行优化,但仍然使用clrh,而不是两次clrb。类似
的汇编指令有ldw、lduh等等。有人可能碰上读操作也导致SIGBUS,觉得不可理解,
其实读写导致SIGBUS没有本质区别,比如ldw只能读4字节边界上的地址。

bus.c是显式的未对齐。程序员实际最容易面对的是隐式未对齐,主要来自指针的强
制类型转换。下面举例说明这种情形。

--------------------------------------------------------------------------
/*
* Test: SPARC/Solaris 8 64-bit kernel mode
* gcc -Wall -pipe -g -o other_bus other_bus.c
*/
#include <stdio.h>
#include <stdlib.h>

int main ( int argc, char * argv[] )
{
    unsigned int        i = 0x12345678;
    unsigned short int  j = 0x0000;

    j = *( ( unsigned short int * )( ( ( unsigned char * )&i  ) + 1 ) );
    return( EXIT_SUCCESS );
}  /* end of main */
--------------------------------------------------------------------------

$ ./other_bus
总线错误 (core dumped)
$ gdb ./other_bus core
GNU gdb 5.0
#0  main (argc=1, argv=0xffbefc44) at other_bus.c:13
13          j = *( ( unsigned short int * )( ( ( unsigned char * )&i  ) + 1 ) );
(gdb) disas main
Dump of assembler code for function main:
0x10810 <main>   :      save  %sp, -120, %sp
0x10814 <main+4> :      st  %i0, [ %fp + 0x44 ]
0x10818 <main+8> :      st  %i1, [ %fp + 0x48 ]
0x1081c <main+12>:      sethi  %hi(0x12345400), %o1
0x10820 <main+16>:      or  %o1, 0x278, %o0     ! 0x12345678
0x10824 <main+20>:      st  %o0, [ %fp + -20 ]
0x10828 <main+24>:      clrh  [ %fp + -22 ]
0x1082c <main+28>:      lduh  [ %fp + -19 ], %o0
0x10830 <main+32>:      sth  %o0, [ %fp + -22 ]
0x10834 <main+36>:      clr  %i0
0x10838 <main+40>:      b  0x10840 <main+48>
0x1083c <main+44>:      nop
0x10840 <main+48>:      ret
0x10844 <main+52>:      restore
End of assembler dump.
(gdb) i r pc
pc             0x1082c  67628
(gdb)

因此在SPARC架构上编程,一定要留神强制类型转换,务必清楚自己正在干什么,有
没有隐患。

D: yuhuan@SMTH 2004-01-30 11:48

参Linux的mmap(2)手册页

--------------------------------------------------------------------------
使用映射可能涉及到如下信号

SIGSEGV

    试图对只读映射区域进行写操作

SIGBUS

    试图访问一块无文件内容对应的内存区域,比如超过文件尾的内存区域,或者以
    前有文件内容对应,现在为另一进程截断过的内存区域。
--------------------------------------------------------------------------


by scz , <Unix编程/应用问答FAQ>
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP