總線錯誤和段錯誤

總線錯誤和段錯誤


bus error(core dumped) 總線錯誤(信息已經轉儲)

segmetation fault(core dumped)段錯誤(信息已經轉儲)
這種錯誤相信只要你在unix用c,c++這兩種錯誤是常見又是很頭疼的錯誤,目前我也遇到段錯誤的程序,至今未找到錯誤原因。來看看作者怎麼解說的:

產生原因: 當硬件告訴操作系統一個有問題的內存引用時,操作系統通過發送信號給有問題的進程進行交流。(信號是一種事件通知或一個軟件中斷)。普通進程一般對“總線錯誤”或“段錯誤”信號將進行信息轉儲並且終止,俗稱“程序coredump”。
(當然可以設置一個信號處理程序修改程序的缺省反應)。

總線錯誤:
引起原因: 幾乎總是由於對未對齊的讀或寫引起的。它之所以稱爲總線錯誤是因爲對未對齊的內存訪問時,被阻塞的組件就是地址總線。

對齊(alignment)數據項只能存儲在地址是數據項大小的整數倍的內存位置上,這樣可以加速內存訪問。如:訪問一個8字節的double的數據時,地址只能是8的整數倍,所以存儲一個double的地址只能是24,8008,但不能存儲於地址1006因爲它不能被8整除,只要保證這個原則,就可以保證一個原子項數據不會跨頁或cache塊的邊界。

引起總線錯誤的小程序:
union 
{
    char a[10];
    int i;
}u;

int *p =(int*)&(u.a[1]);

*p =17;/*p中未對齊的地址將會引起總線錯誤*/
因爲數組和int的聯合確保了a是按照int的4字節來對齊的,所以“a+1”肯定不是int來對齊的。(後面專門討論下內存對齊問題)

段錯誤:
   引起直接原因:
(1)解除引用一個包含非法值的指針。
(2)解除引用一個空指針(常常是從系統返回,卻未經過檢查)。
(3)未得到正確權限進行訪問。如:向只讀文本段存儲值就回引起段錯誤。
(4)用完了堆棧或堆空間。

   出現頻率來分:
1 壞指針值錯誤:指針賦值前用它來引用內存;或向庫函數傳遞壞指針(系統程序出現壞指針問題很可能還是出自自己的代碼中);指針釋放後還訪問他的內容,
指針釋放後,一定要把它置爲NULL。

2 改寫錯誤:越過數組邊界寫入數據,在動態分配內存兩端寫數據,或改寫一堆管理數據結構(在動態內存兩端寫數據就會引起這種錯誤)。
    p= malloc(256); p[-1]=0; p[256]=0;
          
3 指針釋放引起的錯誤:釋放一個內存塊兩次,或釋放一個未曾用malloc分配的內存,或釋放正在使用中的內存,或釋放一個無效的指針。
    如:
        for(p = start; p; p= p->next)
           {
             free(p);
           }
存在程序對下一次循環中對釋放的指針p進行解除引用。

用dbx可以看出堆棧空間是否用完:
dbx a.out
(dbx) catch SIGSEGV

(dbx) run

...
signal SEGV(segmentation violation ) in <some_routine> at oxeff57708
(dbx)where
如果可以看到調用鏈說明堆棧空間還沒有用完。如果看到以下情景:
fetch at oxeffe7a60 failed --- I/O error
(dbx)
那麼堆棧空間已經用完,上面16禁止數就是可以提取或影射的堆棧地址。

C-SHELL中可以通過limit stacksize 10 來調整堆棧的空間爲10K,進程的總線地址空間仍然收到交換區大小的限制,可以用swap -s命令查看交換區的大小。



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章