一. 前面的话
上次洪哥跟我说,希望多写一些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 ··················
点击关注公众号,免费领学习资料