前段買了本《C專家編程》確實不錯,特別是對內存思考這一章節,(O(∩_∩)O~目前我也只看到這一章節),其中講到了總線錯誤和段錯誤: 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 at oxeff57708 (dbx)where 如果可以看到調用鏈說明堆棧空間還沒有用完。如果看到以下情景: fetch at oxeffe7a60 failed — I/O error (dbx) 那么堆棧空間已經用完,上面16禁止數就是可以提取或影射的堆棧地址。 C-SHELL中可以通過limit stacksize 10 來調整堆棧的空間為10K,進程的總線地址空間仍然收到交換區大小的限制,可以用swap -s命令查看交換區的大小。
新聞熱點
疑難解答