天天看點

C++字元數組越界問題的一個案例分析

賀老師:

  老師,m_szdepartment=new char[strlen(department)+1];為何需要+1呢?在測試裡去掉+1後和這個效果一樣啊,不太明白……求指教……

  學生,楊騰飛

  我回答:

  要給'\0'占個座。是用别人的地盤(越界的部分)儲存了自己的資訊了吧,不定哪次人家要用,運作結果就不一樣了。這恰是最危險的問題。

  他繼續追問:

  可是在定義字元數組時,比如a[4]時,可以輸入5個字元,那麼這個數組的'\0'的位置是不是也占用了别人的?

  我為這個機靈的同學的問題感到激動,讀程式,切忌隻是讀,要會提問題。能自己提出問題,就一定能學好。老師給出解答,接着再提出新問題,自己解答,或再問老師,這就是交流。為着學生提出了好問題,作為老師,我驕傲。我的回答是:

  你提的問題不是一般的好,見我新發表的博文談這個問題。

  下面就是我對這個問題的解答。不妨針對問題設計一個程式試一試。程式是:

  親愛的讀者,讀這篇文章時,請不要隻“讀”,打開你熟悉的程式設計環境,邊讀邊運作。你會發現什麼?

  輸入abcd然後回車,輸出是abcd。cout<<a是将字元數組當字元串輸出的,顯然abcd已經占滿了自己的地盤a[0]到a[3],能夠“如願”輸出,實際上已經侵占了不該占的記憶體a[4]單元。當然,恰好a[4]處給臉,就是'\0'。如果”燙燙燙燙燙燙“不必意外。

  再運作,輸入abcde。我運作的結果是,在vc++6.0中,輸出abcde,并彈出了我們熟悉的記憶體越界錯誤提示。在codeblocks下,輸出abcde,什麼也沒提示。

  請讀者想想,這是一個多麼兇險的bug。

  下面再給出一個程式:

  運作的任務交給讀者了,觀察輸入3個字元、4個字元、5個字元的情形,也可以在多個平台上試試,針對結果想想為什麼。用單步執行的手段跟蹤一下記憶體中的資料存儲,是個強烈建議的辦法。

  下面是為a和b數組輸入3個字元後(分别是abc和hij),利用單步執行看到的結果:

  

C++字元數組越界問題的一個案例分析

  下面是為a和b數組輸入5個字元後(分别是abcef和hijkl),利用單步執行看到的結果:

C++字元數組越界問題的一個案例分析

  從中看出,vc++6.0中,先定義的a數組的位址大于後定義的數組b的位址,本來為a中輸入了abcde,侵占了别人的地盤,随後為b輸入hijkl,侵占的就是a的地盤,b[4]即a[0]為l,b[5]即a[1],存儲的是'\0'!

  下圖是在codeblocks下,用同樣的輸入調試截出的結果,結果一樣:

C++字元數組越界問題的一個案例分析

  接下來,再給一個程式,其實就是将輸入a和b的順序換了一下:

  運作結果會是怎樣?讀者你自己說吧。不要忘了,用調試工具這個法寶解除你的疑惑。

繼續閱讀