Linux C中令人討厭的段錯(cuò)誤
作者:孫曉明,華清遠(yuǎn)見(jiàn)嵌入式培訓(xùn)中心講師
同學(xué)們?cè)谧鼍毩?xí)的時(shí)候,編譯完程序,執(zhí)行的時(shí)候,有時(shí)會(huì)莫名的出現(xiàn) “Segment fault”,即段錯(cuò)誤,段錯(cuò)誤是讓許多C程序員都頭疼的提示,因?yàn)閷?duì)于這種模糊的提示,很難判斷錯(cuò)誤在哪里。那么什么事段錯(cuò)誤呢?以及怎么發(fā)現(xiàn)程序中的段錯(cuò)誤以及如何避免發(fā)生段錯(cuò)誤呢?
1.什么是段錯(cuò)誤?
所謂的段錯(cuò)誤就是指訪問(wèn)的內(nèi)存超出了系統(tǒng)所給這個(gè)程序的內(nèi)存空間,通常這個(gè)值是由gdtr來(lái)保存的,他是一個(gè)48位的寄存器,其中的32位是保存由它指向的gdt表,后13位保存相應(yīng)于gdt的下標(biāo),最后3位包括了程序是否在內(nèi)存中以及程序的在cpu中的運(yùn)行級(jí)別,指向的gdt是由以64位為一個(gè)單位的表,在這張表中就保存著程序運(yùn)行的代碼段以及數(shù)據(jù)段的起始地址以及與此相應(yīng)的段限和頁(yè)面交換還有程序運(yùn)行級(jí)別還有內(nèi)存粒度等等的信息。一旦一個(gè)程序發(fā)生了越界訪問(wèn),cpu就會(huì)產(chǎn)生相應(yīng)的異常保護(hù),于是segmentation fault就出現(xiàn)了。
通過(guò)上面的解釋,段錯(cuò)誤應(yīng)該就是訪問(wèn)了不可訪問(wèn)的內(nèi)存,這個(gè)內(nèi)存區(qū)要么是不存在的,要么是受到系統(tǒng)保護(hù)的。
2.那什么操作會(huì)引起段錯(cuò)誤呢?
粗略的分一下類:
1)往受到系統(tǒng)保護(hù)的內(nèi)存地址寫(xiě)數(shù)據(jù)
有些內(nèi)存是內(nèi)核占用的或者是其他程序正在使用,為了保證系統(tǒng)正常工作,所以會(huì)受到系統(tǒng)的保護(hù),而不能任意訪問(wèn)。
2)內(nèi)存越界(數(shù)組越界,變量類型不一致等)
3)其他
例如:
<1>定義了指針后記得初始化,在使用的時(shí)候記得判斷是否為NULL
<2>在使用數(shù)組的時(shí)候是否被初始化,數(shù)組下標(biāo)是否越界,數(shù)組元素是否存在等
<3>在變量處理的時(shí)候變量的格式控制是否合理等
3.那么我們?nèi)绾稳グl(fā)現(xiàn)程序中的段錯(cuò)誤呢?
通過(guò)學(xué)習(xí)前人的經(jīng)驗(yàn)和開(kāi)發(fā)的工具,不斷的嘗試和研究,找出更恰當(dāng)?shù)姆椒▉?lái)避免、發(fā)現(xiàn)并處理它。對(duì)于一些常見(jiàn)的地方,我們可以避免,對(duì)于一些“隱藏”的地方,我們要發(fā)現(xiàn)它,發(fā)現(xiàn)以后就要及時(shí)處理,避免留下隱患。
用gdb來(lái)調(diào)試,在運(yùn)行到段錯(cuò)誤的地方,會(huì)自動(dòng)停下來(lái)并顯示出錯(cuò)的行和行號(hào),gdb也是最常用的,如果需要用gdb調(diào)試,記得在編譯的時(shí)候加上-g參數(shù)。
“本文由華清遠(yuǎn)見(jiàn)http://www.embedu.org/index.htm提供”
華清遠(yuǎn)見(jiàn)