2013-12-13 48 views
0
#include <stdio.h> 
#include <stdlib.h> 
int main(int argc, char *argv[]) 
{ 
    int char_freq[26] = {0}; 
    int i = 'a'; 
    int plain_char = getchar(); 
    while(plain_char != EOF) 
    { 
     char_freq[plain_char-'a']++; 
     plain_char = getchar(); 
    } 
    while(i <='z') 
    { 
     printf("%c %d \n",i,char_freq[i-'a']); 
     i++; 
    } 
    return EXIT_SUCCESS; 
} 

在上面的程序中,我試圖製作一個頻率表並使用ASCII值進行播放。問題是我沒有檢查plain_char ASCII值是在小寫字母的範圍內,如果我輸入Aplain_char然後65-97 = -32數組索引,我增加它,我不應該得到分段錯誤?但程序運行仍然正常?無段錯誤

回答

3

當您處於程序允許的內存區域之外時,只有在定義的數組之外,並且這並不意味着您位於程序的內存區域之外,只會出現分段錯誤。它可以讀取垃圾數據和/或覆蓋程序數據的其他部分,或者在某些情況下甚至可能導致緩衝區溢出攻擊機會的程序代碼。

當然,你的陣列應該在你的存儲區域的開始或結束,那麼你得到分段錯誤。數組放入內存的位置由編譯器和鏈接器決定。類似的,當你在途中,走出你的數組範圍。試試例如char_freq[2^31]這可能會給你一個分段錯誤。

+0

我怎麼知道有多少內存分配給我的程序? – user2688772

+0

@ user2688772你不應該在意。你應該只關心你明確分配的內存。 (我們也應該說程序而不是程序) –

0

你在這裏有一個未定義的行爲,這意味着一切都可能發生。

3

寫入數組的界限是未定義的行爲。不足爲奇,這意味着程序的行爲沒有定義,什麼都可以發生。一些可能發生的例子:

  • 該程序可能會崩潰併產生分段錯誤或類似情況。
  • 該程序可以執行得很好。
  • 該程序可能會執行看起來很好,稍後崩潰。
  • 該程序可能會破壞自己的變量/自己的堆棧,導致任何隨機結果。

依此類推。

+1

+1,但我會質疑你的「不太出人意料」。我的經驗是,人們常常爲*未定義的「未定義的行爲」而感到驚訝。 – ruakh

+0

@ruakh不斷提問像「未定義行爲如何定義行爲」的人應該考慮一個不同的職業。或者他們會發現自己編寫的代碼像'#if!defined behavior behave_as(behavior); #endif'。 – Lundin