C++:原來你程序的BUG是這樣來的

編程老大叔 發佈 2019-12-20T20:52:01+00:00

BUG原意是小蟲子、昆蟲的意思,據傳該詞被用在編程領域並且成為計算機領域專業術語是因為很久以前一個叫葛麗絲·霍波的」程式設計師/媛「,她在調試設備時出現故障,拆開設備後,發現有隻飛蛾被夾扁在觸點中間,從而「卡」住了設備運行。

BUG原意是小蟲子、昆蟲的意思,據傳該詞被用在編程領域並且成為計算機領域專業術語是因為很久以前一個叫葛麗絲·霍波的」程式設計師/媛「,她在調試設備時出現故障,拆開設備後,發現有隻飛蛾被夾扁在觸點中間,從而「卡」住了設備運行。於是,她聯想到自己寫程序時找問題的場景,詼諧的把程序故障稱為「臭蟲(BUG)」,把找BUG叫做DEBUG;

世界上沒有不討厭BUG的程式設計師,多少程式設計師為BUG揪掉了滿頭青絲。那麼程序中為什麼會出現BUG?這些BUG都是怎麼來的呢?

粗心寫錯、用錯

大部分的BUG都是由於程式設計師粗心大意,或是用錯變量、或是文件路徑寫錯、或者是函數參數傳錯等。要想避免這種由於粗心大意造成的BUG,除了要細心之外還需要規範自己的代碼習慣。如:變量命名嚴格遵循駝峰原則;靈機一動處的代碼邏輯一定要注釋清楚,不然後續在維護代碼時我保證你會一臉懵逼,強行改動可能就會造成變量用錯,邏輯破壞等BUG;多層循環,每層循環變量一定要命名清楚,不要用i,j,k等毫無意義的變量名;

int a ,b ,c, d, e, f = 0 ;

string s1,s2,s3 = "";

for (int i = 0; i < 3; i++)

{

for (int j = 0; j < 4; j++)

{

for (int k = 0; k < 5; k++)

{

}

}

}

小駝峰命名法

小駝峰式命名規則:firstName, camelCase

變量一般用小駝峰法標識。駝峰法的意思是:除第一個單詞之外,其他單詞首字母大寫。

大駝峰命名法:FirstName, CamelCase

大駝峰法,在小駝峰基礎上把第一個單詞的首字母也大寫了。常用於類名,命名空間等;

基礎不紮實

這個很好理解,就是編程基礎不紮實,犯一些基本錯誤;如:

string str = "i love u" ;

if(str.find("y"))cout<<"find"<<endl;

find函數若是未在目標字符串中找到子串,則會返回-1,這裡程式設計師錯誤將負數自認為是false,其實不是,在編程界只有0和非0之分;

又比如:數據類型沒弄清楚,忽略了隱式轉換:

double putIn = 123.456;

double result = 1/3*putIn ;

這個結果不管putIn是何值,結果都是0,;因為1/3 = 0 ;

考慮不周全,邊界極限情況未考慮

程式設計師在開發一項業務時,除了需要考慮到要將業務邏輯實現,還需要考慮到各種極限的情況。例如,很多遊戲開發人員,只是考慮常規操作玩法,一旦有人進行極端操作可能就會導致程序出現一些莫名的BUG。這一點,就連目前業界頂尖的騰訊諸如王者榮耀、英雄聯盟等團隊都不能完全避免;例如,最簡單的在算兩個數相除時:

double result,dividend,divider = 0 ;

cin>>dividend>>divider;

result = dividend/divider ;

cout<<result<<endl;

未做足夠的安全檢查

這一點在C/C++中是經常出現BUG的地方,因為C/C++對安全檢查做的不夠,很多地方都需要程式設計師自己去處理可能會出現的異常,不像Python等高級語言,很多異常語言本身已經給你定義好了,出異常時會拋出,對應catch處理就可以。如:常見的C++中vector容器的下標訪問不作越界檢查,出錯時直接中斷程序。又或者是用指針時,未對其進行空指針驗證,直接就用;

//數組越界

vector<int> vecTest(3) ;

/*N行業務代碼*/

int test_4 = vecTest[4] ;

//未做空指針驗證

int* ptr = nullptr ;

/*N行業務代碼*/

*ptr = 1 ;

正確寫法應該是:

//數組越界

vector<int> vecTest(3) ;

/*N行業務代碼*/

int test_4 = 0 ;

int index = 4 ;

if(vecTest.size()>=index+1)test_4 = vecTest[index];

else throw "out of range" ;

//或者直接用.at()方法

int test_4 = vecTest.at(4);

//未做空指針驗證

int* ptr = nullptr ;

/*N行業務代碼*/

if(ptr!=nullptr)*ptr = 1 ;

其實也不是什麼難事,就是各位在寫的時候不要偷懶。

濫用指針,內存泄露

指針是個好東西,同時它也是一個壞東西,如果用的不好就會導致程序出現嚴重的BUG,如:內存泄露和野指針。舉例:兩個指針同時指向同一塊內存,但是程式設計師可能在某處將這塊內存通過其中一個指針刪除了,此時如果在後面的代碼中再去用另外一個指針時一定會出錯;又或者就只有一個指針,編程者自己釋放了內存,但是指針沒有指向NULL,後來又拿來用,同樣也一定會出錯:

char* ptr1 = new char[20] ;

strcpy(ptr1,"i love u") ;

char* ptr2 = ptr1 ;

/*N行代碼後*/

delete ptr1 ;

/*N行代碼後*/

if(ptr2!=nullptr)cout<<ptr2<<endl;

正確的做法是:釋放內存後,將對應的所有指針都指向NULL;

elete ptr1 ;

ptr1 = nullptr ;

ptr2= nullptr ;

有時後可能不是程式設計師粗心造成這樣,比如對象中存在指針時,如果採用的淺拷貝,極有可能出現這樣的情況,而且沒有足夠經驗的程式設計師是很難察覺到的;

總結

就像當初小編的老師說的,沒人敢說他沒寫過BUG。只要大家規範代碼,基礎紮實,細心,考慮問題全面就一定能寫出一手優質代碼。

關鍵字: