让我印象深刻并很喜欢的一个Bug

发表于:2016-12-16 11:41

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:张书情    来源:51Testing软件测试网采编

  后记
  很高兴发现了这个问题,这是一次很好的学习过程。自那以后,我对于如何声明函数很谨慎。但愿这是好事。
  不过,我对这件事做了反思。
  为何这个错误会出现?正如前所述,我开始使用这个size()函数的原因是为了消除编译器警告信息。在C++的标准库中,大多数容器的size()函数返回类型size_t的整数,这是无符号整数。所以,如果你编译下面这样的一段代码:
  for (int i = 0; i < v.size(); i++) {
  }
  编译器就会给出关于带符号整数和无符号整数之间的比较的警告信息。看到大量这样的警告信息很快会让人乏味。另一个相关问题如下。比如说你想迭代处理除容器最后一个元素之外的所有部分。你可能这样来实现这个部分:
  for (int i = 0; i < v.size() - 1; i++) {
  }
  但是容器为空时,这段代码无法正确运行。由于v.size()返回的是无符号整数(这里值为零),减1会下溢,给出size_t的最大表示值,而不是预期的-1。这反过来会导致无限循环。
  要解决上述两个问题,一个明显的简单办法就是将结果转换为整数,如下所示:
  for (int i = 0; i < (int)v.size() - 1; i++) {
  }
  但是由于经常为循环编写这种代码,每次编写会很烦人。我认为在编程比赛界很常见的另一个办法是,定义诸如下列宏命令之类的命令:
  #define SZ(c) (int)(c).size()
  然而像下面这样使用它:
  for (int i = 0; i < SZ(v) - 1; i++) {
  }
  当我开始参加编程比赛时,可能见过这个宏命令好几次;有时我决定编写自己的版本。我觉得SZ不好看,更习惯于键入size,于是我想继续这么做。但是用名称size创建宏命令会有点危险,因为size是个常见的变量名称,这会引起麻烦。于是,我走另一条路,创建了下列函数,而不是宏命令:
  template <class T> int size(T x) { return x.size(); }
  我不确信为什么没有让参数由引用传递,但是确信在我开始参加编程比赛之前(因而在我编写这个函数之前)知道区别所在。但是很容易犯这个错误,哪怕是经验丰富的编程人员,要是他在实现这种看似微不足道的函数时没有高度集中注意力的话。
  我还想知道为什么之前没有遇到问题。一个原因可能是,我缺乏经验,不知道这种循环会运行多快。另一个因素也是这个事实,参加编程比赛的程序员通常没必要为编写拷贝构造 函数和析构函数而操心。进程终结时,通常我们就让C++运行时环境释放所有的内存。至少我确信我在发现这个错误时,我在库中的数据结构没有一个实现这些构造函数。
  我试着准确查明何时开始使用这个函数。我查看了在TopCoder和Codeforces上的提交历史。在TopCoder上,我发现没有在2011年10月26日的比赛中使用这个函数(遗憾的是,你不得不登录到TopCoder才能访问链接)。然而,我在2011年11月12日的比赛中使用了那个函数。发觉这一点让我崩溃。这个错误出现在了我从2011年11月12日直到2013年11月3日的所有编程比赛解决方案当中。那可是我参加编程比赛的头两年!
  举例说,我发现了提交的这个代码,当时是为了解决参与Codeforces的第二场比赛的第一个问题。我试图解决头两个问题,但结果证明我的两个解决方法都速度太慢了。然而,就我提交的解决第一个问题的方案而言,我只是增添了那个字母(&),让size()函数由引用传递,提交的内容通过了。我为自己过去的愚蠢而感到可笑。
  最近我又分析了几年前解决不了的一个问题,不过试着实现一种解决办法。我仔细阅读了问题,提出了解决办法。我还记得,那是我第一次想到的同一个解决方法。由于有点懒,我找到了原来的代码,而不是从头开始实现一切。我分析了代码,似乎很正常。于是我提交了,但结果运行速度太慢了。我花了好长时间来检查代码,但是不明白为何这么慢。但突然之间,我发现了问题之所在。那个旧的、坏的size()函数,我添加了&,重新提交了,通过了!
  尽管我以为自己在多年前解决了这个错误,但直到今天它仍在为我敲警钟!
22/2<12
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号