2017-07-28 85 views
0

如果我嘗試運行此代碼並給出例如「Hello」(超過3個字符)作爲scanf的輸入,則數組str不會溢出。這聽起來有點奇怪,但我當然錯過了一些東西。有人知道這裏有什麼問題嗎?非常感謝!數組不溢出(C語言)

char str[3]; 
scanf("%s", str); 
printf("%s\n", str); 
+2

覆蓋數組邊界是[未定義行爲](https://stackoverflow.com/documentation/c/364/undefined-behavior/2144/accessing-memory-beyond-allocated-chunk)。如果通過「不溢出」表示「打印出沒有分割錯誤」,那麼這次你就很幸運了。 「你好」不適合'str',所以你是溢出來的。或者真的是_unlucky_,因爲你會認爲一切都很好,然後當你最不期待的時候你的程序會崩潰。 – yano

+1

沒有真正相關,但只是要注意輸入超過2個字符將調用ub。有幾種運行時工具可以用來捕獲這種錯誤,警告標誌不會捕獲這些錯誤,但對於捕獲其他ub調用代碼(例如試圖讀取未初始化的變量)仍然有用。 – George

+0

這實際上很奇怪,因爲我正在嘗試輸入每一個出現在我腦海中的字符串,並且沒有顯示任何錯誤。也許這只是一個「現代」編譯器,可以自動處理所有這些。我只是使用Mac上的Terminal編譯它,然後輸入「gcc -o fs main.c」,然後在那裏運行它。 –

回答

1

我試圖運行你的代碼,它確實段錯誤:

./main 
ofejnhofewnhouwnofwbeqofenoifwenofwenoubwuiowgebouwegfougewfnbnbboue 
ofejnhofewnhouwnofwbeqofenoifwenofwenoubwuiowgebouwegfougewfnbnbboue 
Segmentation fault (core dumped) 

我不知道你想有多少個字符在scanf()通過,但你要知道,有時候編譯器在保存的ESP/EIP和初始變量之間執行填充。

尤其是,在這裏,您正在堆棧上創建一個3字節的內存區域,編譯器會首先將其舍入爲4(或在x64上爲8)。但即使如此,它可能會增加更多空間。

gdb,一個disass main給我:

0x000000000040057d <+0>: push %rbp 
    0x000000000040057e <+1>: mov %rsp,%rbp 
    0x0000000000400581 <+4>: sub $0x20,%rsp 

sub 0x20爲32個字節,明顯的方式超過3個字節。

不要指望一個嚴格的「虛擬」C到彙編指令,現在編譯器執行了大量的優化和決定,你可能會意識到。

試圖找到您的緩衝區和EIP通常需要進行蠻力,而是一個聰明的黑客可能會發現更有趣的方法之間的確切字節範圍... ;-)

+1

明白了。謝謝 :) –

1

C運行時沒有問題錯誤/警告消息,但會產生不正確的結果。 檢查溢出/下溢是你的責任。

2

你說「數組str不溢出」,但你怎麼知道的?你是如何期待溢出顯現出來的?

其實這個數組確實有溢出。你只是「幸運」,並沒有(可見的)反響。

對計算機編程理解棘手的一件事是規則的執行可能很不一致。 (計算機編程與這方面的生活不同。)如果交叉路口的信號顯示「不要走路」,但是沒有汽車出現,所以你無論如何都要穿過街道,如果沒有警察立即出現,並且寫信給你,你有多驚訝jaywalking的機票?這基本上就是這裏發生的事情。