段錯誤(Segment Fault )莫名的問題

2021-05-22 22:37:53 字數 1396 閱讀 1258

段錯誤或段違規(segmentation violation)應該已經很清楚,之前有過一篇文章介紹過「段模型」。

在一般硬體中,段錯誤是由於「記憶體管理單元」(負責支援虛擬記憶體的硬體)的異常所致,而該異常則通常是由於解除引用乙個未初始化或非法值的指標引起的。如果指標引用乙個並不位於你的位址空間中的位址,作業系統便會對此進行干涉。乙個小型的會引起段錯誤的程式如下:

int *p = 0;

*p = 17;     //引起乙個段錯誤

乙個微妙之處是,導致指標具有非法的值通常是由於不同的程式設計錯誤所引起的。和匯流排錯誤不同,段錯誤更像是乙個間接的症狀而不是引起錯誤的原因。

乙個更糟糕的微妙之處是,如果未初始化的指標恰好具有未對齊的值(對於指標所要訪問的資料而言),它將會產生匯流排錯誤,而不是段錯誤。對於絕大多數架構的計算機而言確實如此,因為cpu先看到位址,然後再把它傳送給mmu(記憶體管理單元)。

通常導致段錯誤的幾個直接原因:

(1) 解除引用乙個包含非法值的指標;

(2) 解除引用乙個空指標(常常由於從系統程式中返回空指標,並未經檢查就使用)。

(3) 在未得到正確的許可權時進行訪問。例如,試圖往乙個只寫的文字段儲存值就會引起段錯誤。

(4) 用完了堆疊或堆空間(虛擬記憶體雖然巨大但絕非無限)。

下面這個說法可能過於簡單,但在絕大多數架構的絕大多數情況下,匯流排錯誤意味著cpu對程序引用記憶體的一些做法不滿,而段錯誤則是mmu對程序引用記憶體的一些情況發生抱怨。

以發生頻率為序,最終可能導致段錯誤的常見程式設計錯誤是:

1. 壞指標值錯誤:在指標賦值之前就用它來引用記憶體,或者向庫函式傳送乙個壞指標(不要上當!如果編譯器顯示系統程式中出現了段錯誤,並不是因為系統程式引起了段錯誤,問題很可能還在存在於自己的**中)。第三種可能導致壞指標的原因是對指標進行釋放之後再訪問它的內容。可以修改free語句,在指標釋放之後再將它置為空值。

free(p);  p = null;

這樣,如果在指標釋放之後繼續使用該指標,至少程式能在終止之前進行資訊轉儲。

2. 改寫(overwrite)錯誤:越過陣列邊界寫入資料,在動態分配的記憶體兩端之外寫入資料,或改寫一些堆管理資料結構(在動態分配的記憶體之前的區域寫入資料就很容易發生這種情況)。

p = malloc(256);  p[-1] = 0;  p[256] = 0;

3. 指標釋放引起的錯誤:釋放同乙個記憶體塊兩次,或釋放一塊未曾使用malloc分配的記憶體,或釋放仍在使用中的記憶體,或釋放乙個無效的指標。乙個極為常見的與釋放記憶體有關的錯誤就是在 for(p=start; p; p=p->next)這樣的迴圈中迭代乙個鍊錶,並在迴圈體內使用 free(p) 語句。這樣,在下一次迴圈迭代時,程式就會對已經釋放的指標進行解除引用操作,從而導致不可預料的結果。

詳細出處參考:http://www.itqun.net/content-detail/238672.html

出現segment fault 錯誤的幾種原因

segment fault 段異常各種原因 www.myexception.cn 發布於 2012 11 26 11 48 50 瀏覽 24次 0 segment fault 段錯誤各種原因 一 造成segment fault,產生core dump的可能原因 1.記憶體訪問越界 a 由於使用錯誤的...

段錯誤?打的就是段錯誤!!

呵,段錯誤?自從我看了這篇文章,我還會怕你個小小段錯誤?請開啟你的linux終端,跟緊咯,準備發車!嘟嘟嘟噠 include void errfunc intmain 這段 拿去執行,肯定段錯誤。系統會在程式崩潰的那一剎那將整個核心的資訊記錄在乙個檔案裡邊。如果你是第一次,那麼ls是查不到的。這樣 ...

Segment fault 常見原因

1.引用空指標 2.野指標 3.訪問越界 造成的原因有多種 主觀原因 1.新申請指標忘記賦null,也忘記分配空間,直接使用造成非法訪問。2.為指標賦值時,位址經過計算而來。計算過程有問題,導致賦值的位址不正確,比如位址經過計算涉及到型別轉換之類操作,很容易因為型別轉換造成截斷。客觀原因 3.儲存指...