程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> C++字符數組越界問題的一個案例分析

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

編輯:C++入門知識

賀老師:


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

我回答:
  要給'\0'占個座。是用別人的地盤(越界的部分)保存了自己的信息了吧,不定哪次人家要用,運行結果就不一樣了。這恰是最危險的問題。

他繼續追問:
  可是在定義字符數組時,比如a[4]時,可以輸入5個字符,那麼這個數組的'\0'的位置是不是也占用了別人的?

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

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

 


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


[cpp]
#include <iostream>   
using namespace std; 
int main()  
{  
    char a[4]; 
    cin>>a; 
    cout<<a<<endl; 
    return 0;  

#include <iostream>
using namespace std;
int main()
{
 char a[4];
 cin>>a;
 cout<<a<<endl;
 return 0;
}  親愛的讀者,讀這篇文章時,請不要只“讀”,打開你熟悉的編程環境,邊讀邊運行。你會發現什麼?

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

  再運行,輸入abcde。我運行的結果是,在VC++6.0中,輸出abcde,並彈出了我們熟悉的內存越界錯誤提示。在codeBlocks下,輸出abcde,什麼也沒提示。
  請讀者想想,這是一個多麼凶險的Bug。
  下面再給出一個程序:


[cpp] 
#include <iostream>   
using namespace std; 
int main()  
{  
    char a[4],b[4]; 
    cin>>a; 
    cin>>b; 
    cout<<a<<endl; 
    cout<<b<<endl; 
    return 0;  

#include <iostream>
using namespace std;
int main()
{
 char a[4],b[4];
 cin>>a;
 cin>>b;
 cout<<a<<endl;
 cout<<b<<endl;
 return 0;
}  運行的任務交給讀者了,觀察輸入3個字符、4個字符、5個字符的情形,也可以在多個平台上試試,針對結果想想為什麼。用單步執行的手段跟蹤一下內存中的數據存儲,是個強烈建議的辦法。

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

  \
 


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

\

  


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

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

  \

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


[cpp] 
#include <iostream>   
using namespace std; 
int main()  
{  
    char a[4],b[4]; 
    cin>>b; 
    cin>>a; 
    cout<<a<<endl; 
    cout<<b<<endl; 
    return 0;  

#include <iostream>
using namespace std;
int main()
{
 char a[4],b[4];
 cin>>b;
 cin>>a;
 cout<<a<<endl;
 cout<<b<<endl;
 return 0;
}  運行結果會是怎樣?讀者你自己說吧。不要忘了,用調試工具這個法寶解除你的疑惑。


 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved