理解SIGBUS與SIGSEGV

來源:互聯網
上載者:User
理解SIGBUS與SIGSEGV
Searched by google


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

SIGBUS與SIGSEGV訊號的一般區別如下:

1) SIGBUS(Bus error)意味著指標所對應的地址是有效地址,但匯流排不能正常使用該
指標。通常是未對齊的資料訪問所致。

2) SIGSEGV(Segment fault)意味著指標所對應的地址是無效地址,沒有實體記憶體對
應該地址。

A: scz 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
#include

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 : save %sp, -128, %sp
0x10814 : st %i0, [ %fp + 0x44 ]
0x10818 : st %i1, [ %fp + 0x48 ]
0x1081c : sethi %hi(0x12345400), %o1
0x10820 : or %o1, 0x278, %o0 ! 0x12345678
0x10824 : st %o0, [ %fp + -20 ]
0x10828 : clr [ %fp + -24 ]
0x1082c : add %fp, -20, %o0
0x10830 : st %o0, [ %fp + -28 ]
0x10834 : ld [ %fp + -28 ], %o0
0x10838 : clrb [ %o0 ]
0x1083c : ld [ %fp + -28 ], %o0
0x10840 : add %o0, 1, %o1
0x10844 : st %o1, [ %fp + -24 ]
0x10848 : ld [ %fp + -24 ], %o0
0x1084c : clrh [ %o0 ]
0x10850 : clr %i0
0x10854 : b 0x1085c
0x10858 : nop
0x1085c : ret
0x10860 : 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進行最佳化,但仍然使用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
#include

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 : save %sp, -120, %sp
0x10814 : st %i0, [ %fp + 0x44 ]
0x10818 : st %i1, [ %fp + 0x48 ]
0x1081c : sethi %hi(0x12345400), %o1
0x10820 : or %o1, 0x278, %o0 ! 0x12345678
0x10824 : st %o0, [ %fp + -20 ]
0x10828 : clrh [ %fp + -22 ]
0x1082c : lduh [ %fp + -19 ], %o0
0x10830 : sth %o0, [ %fp + -22 ]
0x10834 : clr %i0
0x10838 : b 0x10840
0x1083c : nop
0x10840 : ret
0x10844 : restore
End of assembler dump.
(gdb) i r pc
pc 0x1082c 67628
(gdb)

因此在SPARC架構上編程,一定要留神強制類型轉換,務必清楚自己正在幹什麼,有
沒有隱患。

D: yuhuan@smth.org 2004-01-30 11:48

參Linux的mmap(2)手冊頁

--------------------------------------------------------------------------
使用映射可能涉及到如下訊號

SIGSEGV

試圖對唯讀映射地區進行寫操作

SIGBUS

試圖訪問一塊無檔案內容對應的記憶體地區,比如超過檔案尾的記憶體地區,或者以
前有檔案內容對應,現在為另一進程截斷過的記憶體地區。
--------------------------------------------------------------------------

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.