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