example - segmentation fault: 11 c++




什麼是分段錯誤? (8)

分段錯誤也是由硬件故障引起的,在這種情況下是RAM存儲器。 這是不太常見的原因,但是如果您在代碼中找不到錯誤,也許memtest可以幫助您。

在這種情況下的解決方案,更改RAM。

編輯:

這裡有一個參考: 硬件分割故障

什麼是分段錯誤? C和C ++有什麼不同? 分段錯誤和懸掛指針如何相關?


值得注意的是,分段錯誤不是由直接訪問另一個進程內存引起的(這是我有時聽到的),因為這是不可能的。 使用虛擬內存,每個進程都有自己的虛擬地址空間,並且無法使用任何指針值訪問另一個進程。 例外是共享庫,這些共享庫映射到(可能)不同的虛擬地址和內核內存,它們在每個進程中都以相同的方式映射(為了避免系統調用時TLB刷新,我認為)。 而像shmat這樣的東西) - 這些就是我所謂的“間接”訪問。 但是,可以檢查它們通常遠離流程代碼,我們通常能夠訪問它們(這就是為什麼它們在那裡,但以不正確的方式訪問它們將產生分段錯誤)。

但是,如果以不正確的方式訪問我們自己的(進程)內存(例如嘗試寫入不可寫入的空間),則會發生分段錯誤。 但最常見的原因是訪問虛擬地址空間的一部分,它根本沒有映射到物理地址空間。

而這一切都與虛擬內存系統有關。


分段錯誤是由進程未在其描述符表中列出的頁面請求引起的,也可能是它列出的頁面的無效請求(例如,在只讀頁面上的寫入請求)。

懸掛指針是一個指針,可能指向或不指向有效頁面,但會指向“意外”內存段。


根據維基百科:

如果程序試圖訪問不允許訪問的內存位置,或嘗試以不允許的方式訪問內存位置(例如,試圖寫入只讀位置或覆蓋部分操作系統)。


當進程(程序的運行實例)試圖訪問其他進程正在使用的只讀內存地址或內存範圍或訪問不存在(無效)的內存地址時,會發生分段錯誤懸掛引用(指針)問題意味著試圖訪問內容已經從內存中刪除的對像或變量,例如:

int *arr = new int[20];
delete arr;
cout<<arr[1];  //dangling problem occurs here

簡而言之:分段錯誤是操作系統向程序發送一個信號,說明它檢測到非法的內存訪問並且過早地終止程序以防止內存被損壞。


說實話,正如其他海報所說,維基百科有一個非常好的文章, 所以看看那裡。 這種類型的錯誤非常常見,常被稱為“訪問衝突”或“常規保護錯誤”等其他內容。

它們在C,C ++或任何允許指針的其他語言中沒有區別。 這些類型的錯誤通常是由指針引起的

  1. 在正確初始化之前使用
  2. 在它們指向的內存已經被釋放或刪除之後使用。
  3. 用於索引位於數組邊界之外的索引數組中。 這通常只在您對傳統數組或C字符串進行指針數學計算時,而不是基於STL / Boost的集合(使用C ++)。

雖然Zoul的答案解釋了什麼是分段錯誤,但我發現這些類型的錯誤可能特別難以捕捉,尤其是在您對C ++或C等低級語言不熟悉的情況下。這裡有一些常見的方法來獲取程序中的段錯誤:

printfscanf語句中的格式控製字符串不正確

格式控製字符串應該具有相同數量的轉換說明符( %s%d等),因為printfscanf具有要打印或讀取的參數。 這同樣適用於fprintffscanf

不使用&參數到scanf

函數scanf將格式控製字符串和變量的地址作為參數,在該變量中將放置它讀取的數據。 & (地址)運算符用於提供變量的地址。

超出邊界數組引用

確保你沒有違反你使用的任何數組的邊界; 也就是說,您沒有為數組下標數組,其值小於其最小元素的索引或大於其最高元素的索引。 Valgrind可以派上用場來檢測這種引用 - 你可以使用valgrind--tool=exp-sgcheck標誌。

訪問未初始化的指針

指針變量在被訪問前必須被分配一個有效的地址。 確保你已經初始化所有的指針指向一個有效的內存區域。

& (地址)和* (取消引用)操作符的使用不正確

使用這些時需要小心,特別是通過引用/使用指針傳遞參數時。

殼牌限制

有時,分段錯誤不是由程序中的錯誤引起的,而是由系統內存限制設置得太低而引起的。 通常這是堆棧大小的限制導致這種問題(堆棧溢出)。 要檢查內存限制,請在bash使用ulimit命令。

使用gdb調試

您可以使用調試器gdb來查看程序轉儲的core文件的回溯。 每當程序出現段錯誤時,他們通常會在崩潰時將內存內容轉儲到core文件中( core dumped )。 使用-g標誌編譯你的程序,在gdb運行並使用bt (backtrace)。





segmentation-fault