我见过哪些意想不到的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实际数组里每一个元素得到数是 0 x 3 f 3 f 3 f 3 f = 2314885530818453536 0x3f3f3f3f=2314885530818453536 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了。但是写下一道题的时候我以为 l l ll 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)的知识增加了,请您点个赞再离开,如果不嫌弃的话,点个关注再走吧,日更博主每天在线答疑 ! 当然,也非常欢迎您能在讨论区指出此文的不足处,作者会及时对文章加以修正 !如果有任何问题,欢迎评论,非常乐意为您解答!( •̀ ω •́ )✧