我见过哪些意想不到的bug?
这里主要指的是我用C++打比赛刷题时遇见的bug,但我感觉工程上可能也会碰见。
像我这种蒟蒻的ACMer(ICPCer ?)打比赛经常出现神奇的bug,找了半个小时都找不到,果然之前有人跟我说debug还不如重新敲 。但是一般的bug直接用小黄鸭debug大法,效果超群,只需要过一遍一般都能找到,但是往往存在一些让我意想不到的bug,怎么看都看不出来(往往是我对这里的基础概念掌握的不够扎实),所以我打算写一篇博客,记录一下我的奇怪的WA,希望不会有下次。(以后再有幸遇见了还会更新的)
一、memset函数的使用细节导致的WA
注:WA是答案错误
memset(dis,0x3f,sizeof dis);
这里看上去没什么问题,但是如果dis
是一个long long
型的指针,那么这里就会WA,因为作为一个指针,sizeof dis
得到的就是8字节,而不是想要的整个数组的空间。这里使用memset
函数是像把dis指针所代指的数组的n个元素赋值为一个极大值,注意memset
函数赋值赋的值必须二进制下每一位相同,memset
是以二进制下赋值的,写作0x3f
实际数组里每一个元素得到数是 0x3f3f3f3f=2314885530818453536。
所以这里应该写成:
memset(dis,32,(n+1)*8);
这里两个细节:
- (n+1)要乘以8,因为我这里使用的是long long 型,占8个字节,如果是int型需要占4个字节。
- n要+1再乘
二、long long的锅引发的MLE
注:MLE是内存超限
typedef long long ll;
我之前有段时间比较喜欢用long long 因为一般一道题的内存很大,很少遇见MLE,直接用long long 也可以防止一些数据上的坑,可能数据直接爆int了,但是都用long long 就可能造成一个后果就是MLE,因为long long占8个字节,是int 的整整两倍,所以我就做过一道题全开long long 直接MLE了,直接把这句话:typedef long long ll;
改成:typedef int ll;
就AC了。但是写下一道题的时候我以为 ll还是long long,把int型的数用printf("%lld\n",ans);
输出,不管是多少都会直接输出0,又WA了一波……
三、queue里的坑让我RE
注:RE是指运行错误,运行时出现错误(指的是运行的时候系统崩溃了QWQ),一般有一下几种情况:
- 除以零
- 数组越界
- 数组开小了
- 指针越界
- 使用已经释放的空间
- 数组开得太大,超出了栈的范围,造成栈溢出
还有一些情况也会RE,比如用map的时候想要输出mp[a]的值,但是mp里a是不存在的,这时候就会RE,应该使用find函数先查找是否存在a这个key值。若mp.find(a)==mp.end()
说明不存在a这个值。
这里主要是想说queue的使用
请看这句话:
if(q.top().first>=a[i].first.first||q.empty())
猛一看是不是没什么毛病?
但是这里就会造成RE,因为这里没有先判空就直接取 q 的top若q为空就是不合法的,就会直接RE,所以应该改成:
if(q.empty()||q.top().first>=a[i].first.first)
换一下顺序就ok了,这样就是先判断是否为空,若为空此语句直接为true直接跳过top。
四、字符输入
以后字符输入尽量用cin
,不管是char
还是string
,cin自动忽略换行符和空格符,所以要想输入一句话什么的要用getline(cin,s);
如果用getchar就一定要注意好各种换行符,空格什么的,要在正确的位置多加几个getchar,比较麻烦容易出错。
这些就是我近期遇见的bug,直接让我怀疑人生(之前不是没遇见过,只是我忘了,以后要是有幸遇见的一定更新!),这些bug究其原因是因为我的基础知识不够扎实 因为都是我自学的嘛 大一的我还是太弱了,以后一定好好刷题,好好总结,吸取经验,下次一定还犯!QWQ
注:如果您通过本文,有(qi)用(guai)的知识增加了,请您点个赞再离开,如果不嫌弃的话,点个关注再走吧,日更博主每天在线答疑 ! 当然,也非常欢迎您能在讨论区指出此文的不足处,作者会及时对文章加以修正 !如果有任何问题,欢迎评论,非常乐意为您解答!( •̀ ω •́ )✧