2012-07-21 60 views
0

認真.. 我從上世紀80年代,並與一些業餘時間 我的手想我應該「C」大驚小怪是關於什麼的我想這個崩潰,但它並不

老黑客

(我的背景是第四,它做的事情後到前 讓我學到了很多關於迫使許多錯誤的)

在這種情況下,我已經設置了一小陣,我 想到會是在3個要素大小(0,1,2)

如果我運行彙編,我會想到 我已經得到了一個徹頭徹尾的越界錯誤,但NO- 它編譯OK嬌聲

運行在這一個不很匆忙,但它 不小禿斑好,所有的scratchin' 。


int main() 
{ 
    char members[3][16]; // 3 elements, each 15 char long plus null 

    printf("\n enter something.. "); 
    scanf("%s", members[4]); 

    printf("\n and something else.. "); 
    scanf("%s", members[5]); 

    printf(" %s ", members[4]); 
    printf(" %s\n", members[5]); 

    return 0; 
} 
+1

你寫一個有錯誤的程序,然後認爲它會按照你的期望去做是不合理的。修復錯誤和代碼將做你的期望。 Buggy代碼很難理解和預測正確的代碼。 – 2012-07-21 09:58:11

+1

我聽到你說的話並同意。但偶爾有一次,我有代碼的作品,強迫一個錯誤,確保我明白爲什麼我們不要我們不。想想這樣:不知道的人不知道他們沒有意識到。但是我不去極限。就像在我未來的情況下檢查我的信箱,我發現空間/時間扭曲門戶,併發送自己的指令來建立它 – aremvee 2012-07-21 10:09:05

+5

雖然這並不奏效。你可以在街上行走而不會看到兩條路,也不會碰到汽車,並且認爲它是安全的。那將是一個可怕的錯誤。你沒有朝兩邊看過去,也沒有被汽車撞到。絕對沒有理由讓你感到驚訝,當然這並不意味着它是安全的。這不是頭痛的人 - 你很幸運。 – 2012-07-21 10:11:43

回答

3

C不做任何邊界檢查。 (Forth也沒有,所以我不確定期望是從哪裏來的。)

溢出數組是未定義的行爲:允許但不是必需的崩潰。在這種情況下,字節恰好與放置局部變量的堆棧幀位於同一虛擬內存頁面中。如果框架朝向頁面的末尾,CPU將識別出錯誤的地址並抱怨溢出。

如果你去幾千字節或幾兆字節,你可能會看到像你期望的東西。

+0

我會嘗試它... – aremvee 2012-07-21 10:18:25

5

訪問陣列外的邊界調用未定義行爲。這意味着任何事情都可能發生,包括沒有任何明顯錯誤的運行。

+0

這個答案令人失望,但它收到了比這裏任何其他更多的upvotes。雖然你的答案在技術上是不可理解的,但如果你仔細閱讀,你可以看到他問爲什麼以及何時離開界限可能是危險的/產生SIGSEV。這不是一個關於standardese的問題,它更多的是關於內存管理和操作系統的問題。 – akappa 2012-07-21 10:51:23

+0

@akappa:這是解釋症狀的最簡單的答案(迄今爲止)。我可以深入討論堆棧和虛擬內存,但我認爲這個問題並不能保證(以目前的形式)。 – 2012-07-21 11:05:18

+0

@akappa - 走出界限總是**危險,特別是因爲它是未定義的。如果不是,它將被定義和安全! – 2012-07-21 16:24:42

0

通常,內存分配在4 kB頁面中。因此在最後一個變量之後會有一些額外的空間,並且您的緩衝區溢出未被檢測到。但是,如果在您的members陣列之後存在另一個變量,並且您寫信給members[4],那麼另一個變量會損壞。

像valgrind和dmalloc這樣的工具通常用於檢測緩衝區溢出。他們通過在變量周圍分配特殊保護區域並檢查沒有人寫入變量來工作。

+1

沒有更多的回覆需要人,你有更好的事情 – aremvee 2012-07-21 10:14:38

0

您錯過了堆棧中的主要返回地址,可能會覆蓋main調用方的一些不重要的數據,因此您的程序不會崩潰。此外,在某些平臺上(例如powerpc),堆棧不用於函數調用,並且返回地址存儲在特殊寄存器中(當需要時將其壓入堆棧)。所以這個不正確的程序不會崩潰是正常的。

更新:此外,在某些系統堆棧增長(到更高的地址)。至少在ARM堆棧增長是可選的。

相關問題