一. 前面的話
上次洪哥跟我說,希望多寫一些bug調試和踩坑經驗的文章。沒問題,反正我是挺會寫bug的。
在C++相關的開發中,有的朋友對一些基本的概念很模糊,用的時候也不注意,然后就呵呵噠了。
我自己也偶爾有這樣的問題,之前用C++寫了一個程序,在測試環境自測無問題,上線后就跪了。
二. bug程序
為了便于敘述,我對原程序進行簡化,如下:
using namespace std;
string getCutRemark(const string &strRemark)
{
string strTmp = strRemark;
unsigned int pos = strTmp.find("|");
if(pos != string::npos)
{
strTmp.erase(strTmp.begin() + pos, strTmp.end());
}
cout << strTmp << endl;
return strTmp;
}
int main()
{
getCutRemark("abc|def"); // ok
getCutRemark("abc"); // error
cout << "ending" << endl;
return 0;
}
這個程序的功能很簡單,意思就是要去掉分隔符和后面的字符。思路是:先找到分隔符,然后刪除分隔符到結尾的字符。
我當時在測試環境做了測試,可是一上線就出問題。為什么呢?因為我沒有區分size_t和unsigned int, 它們是不同的。
在不同自己的機器上,size_t的大小是不同的,我當時的測試機器是32位,此時size_t和unsigned int等價,所以OK.
但是,線上是64位機器,用unsigned int就錯了,看看find函數的返回值類型就知道了,很明顯存在精度丟失問題。
三. 修復bug
修復代碼,再次驗證,就OK了,正確的程序如下:
using namespace std;
string getCutRemark(const string &strRemark)
{
string strTmp = strRemark;
size_t pos = strTmp.find("|");
if(pos != string::npos)
{
strTmp.erase(strTmp.begin() + pos, strTmp.end());
}
cout << strTmp << endl;
return strTmp;
}
int main()
{
getCutRemark("abc|def"); // ok
getCutRemark("abc"); // ok
cout << "ending" << endl;
return 0;
}
四. 趣味結尾
最后,我們來聊2個有趣但無聊的筆試題。說有趣,是因為很多會C++的人,可能掉進陷阱。說無聊,是因為實際開發中,根本不會遇到這種問題。
不要總是想著學習和進步,偶爾娛樂一下,也挺好的。我們需要從生活和工作中,找到一些樂趣,聊作吹水談資。一起來看看,這些題目你能做對嗎?
題目一:
請看程序:
using namespace std;
int main()
{
http://www.baidu.com
int a = 1;
int b = 2;
int c = a + b;
cout << c << endl;
return 0;
}
下列說法正確的是:
A. 編譯出錯 B. 運行出錯
C. c值為3 D. 以上都錯
題目二:
請看程序:
using namespace std;
int main()
{
int a = 1;
int b = 2;
int *p = &b;
int c = a/*p;
cout << c << endl;
return 0;
}
下列說法正確的是:
A. 編譯出錯 B. 運行出錯
C. c值為0 D. 以上都錯
請注意, C++水平不錯的同學,很可能做錯這兩個題目哦。歡迎在評論區討論。最后,祝周末愉快,開心一刻。
·················· END ··················
點擊關注公眾號,免費領學習資料
