下載手機汽配人

centos中出現(xiàn)sigsegv和sigbus錯誤,怎么辦

提問者:網(wǎng)友 2017-12-20
最佳回答
SIGBUS和SIGSEGV也許是我們在平時遇到的次數(shù)最多的兩個內(nèi)存錯誤信號。內(nèi)存問題一直是最令我們頭疼的事情,弄清楚兩個信號的發(fā)生緣由對我們很好的理解程序的運行是大有裨益的。我們來看兩段程序://testsigsegv.cint main() { char *pc = (char*)0x00001111; *pc = 17;}//testsigbus.cint main() { int *pi = (int*)0x00001111; *pi = 17;}上面的代碼那么的相似,我們也同樣用gcc編譯(加上-g選項,便于gdb調(diào)試;平臺Solaris Sparc),執(zhí)行結(jié)果也都是dump core。但通過GDB對core進行觀察,你會發(fā)現(xiàn)細微的不同。第一個例子出的core原因是:Program terminated with signal 11, Segmentation fault. 而第二個例子的core則提示:Program terminated with signal 10, Bus error. 兩者有什么不同呢?這兩段代碼的共同點都是將一個非法地址賦值給指針變量,然后試圖寫數(shù)據(jù)到這個地址。如果要說清楚這個問題,我們就要結(jié)合匯編碼和一些計算機的體系結(jié)構(gòu)的知識來共同分析了。先來看testsigsegv.c的匯編碼:... ...main: !#PROLOGUE# 0 save %sp, -120, %sp !#PROLOGUE# 1 sethi %hi(4096), %i0 or %i0, 273, %i0 st %i0, [%fp-20] ld [%fp-20], %i1 mov 17, %i0 stb %i0, [%i1] nop ret restore... ...我們關(guān)注的是這句:stb %i0, [%i1]從計算機底層的執(zhí)行角度來說,過程是如何的呢?%i0寄存器里存儲的是立即數(shù)17,我們要將之存儲到寄存器%i1的值指向的內(nèi)存地址。這一過程對于CPU來說其指揮執(zhí)行的正常過程是:將寄存器%i0中的值送上數(shù)據(jù)總線,將寄存器%i1的值送到地址總線,然后使能控制總線上的寫信號完成這一向內(nèi)存寫1 byte數(shù)據(jù)的過程。我們再看testsigbus.c的匯編碼:... ...main: !#PROLOGUE# 0 save %sp, -120, %sp !#PROLOGUE# 1 sethi %hi(4096), %i0 or %i0, 273, %i0 st %i0, [%fp-20] ld [%fp-20], %i1 mov 17, %i0 st %i0, [%i1] nop ret restore... ...同樣最后一句:st %i0, [%i1],CPU執(zhí)行的過程與testsigsegv.c中的一致(只是要存儲數(shù)據(jù)長度是4字節(jié)),那為什么產(chǎn)生錯誤的原因不同呢?一個是SIGSEGV,而另一個是SIGBUS。這里涉及到的就是對內(nèi)存地址的校驗的問題了,包括對內(nèi)存地址是否對齊的校驗以及該內(nèi)存地址是否合法的校驗。我們假設(shè)如果首先進行的內(nèi)存地址是否合法的校驗(是否歸屬于用戶進程的地址空間),那么我們回顧一下,這兩個程序中的地址0x00001111顯然都不合法,按照這種流程,兩個程序都應(yīng)該是SIGSEGV導(dǎo)致的core才對,但是事實并非如此。那難道是先校驗內(nèi)存地址的對齊?我們再看這種思路是否合理?testsigsegv.c中,0x00001111這個地址值被賦給了char *pc;也就是告訴CPU通過這個地址我們要存取一個字節(jié)的值,對于一個字節(jié)長度的數(shù)據(jù),無所謂對齊,所以該地址通過對齊校驗;并被放到地址總線上了。而在testsigbus.c里,0x00001111這個地址值被賦給了int *pi;也就是告訴CPU通過這個地址我們要存取一個起碼4個字節(jié)的值,那么對于長度4個字節(jié)的對象,其存放地址起碼要被4整除才可以,而0x00001111這個值顯然不能滿足要求,也就不能通過內(nèi)存對齊的校驗。也就是說SIGBUS這個信號在地址被放到地址總線之后被檢查出來的不符合對齊的錯誤;而SIGSEGV則是在地址已經(jīng)放到地址總線上后,由后續(xù)流程中的某個設(shè)施檢查出來的內(nèi)存違法訪問錯誤。一般我們平時遇到SIGBUS時總是因為地址未對齊導(dǎo)致的,而SIGSEGV則是由于內(nèi)存地址不合法造成的。1) SIGBUS(Bus error)意味著指針所對應(yīng)的地址是有效地址,但總線不能正常使用該指針。通常是未對齊的數(shù)據(jù)訪問所致。2) SIGSEGV(Segment fault)意味著指針所對應(yīng)的地址是無效地址,沒有物理內(nèi)存對應(yīng)該地址。 Linux的mmap(2)手冊頁使用映射可能涉及到如下信號SIGSEGV 試圖對只讀映射區(qū)域進行寫操作SIGBUS 試圖訪問一塊無文件內(nèi)容對應(yīng)的內(nèi)存區(qū)域,比如超過文件尾的內(nèi)存區(qū)域,或者以前有文件內(nèi)容對應(yīng),現(xiàn)在為另一進程截斷過的內(nèi)存區(qū)域。調(diào)試方法:gcc -g 編譯 ulimit -c 20000 之后運行程序,等core dump 最后gdb -c core
回答者:網(wǎng)友
產(chǎn)品精選
搜索問答
還沒有汽配人賬號?立即注冊

我要提問

汽配限時折扣

本頁是網(wǎng)友提供的關(guān)于“centos中出現(xiàn)sigsegv和sigbus錯誤,怎么辦”的解答,僅供您參考,汽配人網(wǎng)不保證該解答的準確性。