下載手機(jī)汽配人

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

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

我要提問(wèn)

汽配限時(shí)折扣

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