2014-12-03 106 views
-2

我寫了這段代碼,並期待quicly出現段錯誤,但似乎允許訪問我不應該能夠訪問的內存段至。訪問超出界限的內存後,不會立即出現分段錯誤

#include<stdio.h> 
int main() 
{ 
    int tab[1]; 
    tab[0]=42; 
    int i; 
    //Expecting Seg Fault from i==1... 
    for(i=0;;i++) 
    { 
     printf("%d \t %d \n", i, tab[i]); 
    } 
    return 0; 
} 

我使用編譯:

gcc -Wall -Wextra my_code.c -o segfault && ./segfault 

在執行時,可變i我得到我分割故障之前達到1000階值。

我的問題是:爲什麼我能夠讀到tab到目前爲止?

PS:使用#include <stdlib.h>並宣佈int * tab = (int*)malloc(sizeof(int));不會改變任何東西......

謝謝,最好成績。

+0

這麼多的蠢貨我不能挑一個。 – 2014-12-03 11:14:05

+0

非常感謝您所有的答案,以及編輯標題。我對這個重複的主題感到厭倦,我不知道正確的錯誤是「超出限制」而不是「分段錯誤」。 – jchd 2014-12-03 13:12:37

回答

2

你的陣列tab將位於棧上的某個地方。當您打印超出陣列的末尾時,實際上是在堆棧上打印其他內存位置的值。

獲取seg故障需要大約1000次迭代的原因是堆棧被映射爲頁面,並且頁面大小通常爲4 KB。一旦你讀了大約1000個整數,你就應該在4000字節左右,並且你已經跨越到一個未映射的頁面。從未映射的頁面讀取是實際觸發seg故障的內容。

請注意,我只是解釋您的系統上發生了什麼。不能保證堆棧將被映射到頁面中,或者頁面大小爲4 KB。從技術上講,你觸發了未定義的行爲,任何事情都可能發生。您可能會發現它在每次迭代時都會執行printf("%p\n", &tab[i]);,並在您收到seg故障之前查看它打印的最後一個地址。如果我對4 KB頁面是正確的,則看到打印的最後一個地址將以ffc結尾,因爲這將是頁面上的最後4個字節。

0

您正在訪問tab的邊界之外,但您仍然在自己的堆棧空間(可能是因爲堆棧幀大於一個字節)。您可以在自己的堆棧上完全讀/寫訪問權限。這實際上是許多裂縫成爲可能的原因。

當您離開您自己堆棧的界限時,會發生分段錯誤。這是您嘗試訪問不屬於您的細分的時刻(因此名稱爲「細分故障」)。

3

當你使用超出限制的內存,您將面臨Undefined behavior。你不能定義東西叫Undefined behavior

在你的情況,這是發生在i = 1000秒,在別人的情況下,它很可能會發生在i=347左右..

分段故障是允許的堆棧地址空間之外內存訪問的結果你程序。它可能正常運行,並顯然適當的工作,如果你在該內存範圍內完成你的執行。一個out-of-bound訪問可能產生vaild內存訪問,直到你沒有穿越堆棧內存區域。

考慮一下自己幸運如果您遇到分段錯誤,因爲這會告訴您,有些事情是錯誤的。否則,你不知道由此產生的恐怖。

注:作爲一個建議,問題的標題應該改爲.. comes up very late什麼simmilar

0

訪問超出數組的到底是不確定的行爲。 任何東西可能會發生。它可能工作,可能會失敗,它可能會重新格式化您的硬盤驅動器,或者可能會在堆棧溢出時發佈問題。

有時賽格故障