代码没问题 程序却有bug?

发表于:2013-1-11 11:34  作者:王然   来源:51Testing软件测试网采编

字体: | 上一篇 | 下一篇 |我要投稿 | 推荐标签: Bug bug 软件测试 缺陷管理

  摘要:相信每个程序员都遇到过“不可能的bug”,代码没有任何问题却出错了!问题肯定是出在操作系统上,或者是工具,甚至是因为计算机硬件的问题?!?当然,魔兽之父也不例外,他在本文中分享了多个处理异常bug的经验。

  今天要分享的故事关于一些我职业生涯中真正遇到的bug。

  这个Bug是Microsoft的错,还是……?

  Diablo发布后几个月,StarCraft团队开始加班来保证游戏的按时完工。那时“距离游戏发布只剩两个月了”,所以每天多加几个小时的班完全是正常的(有时候周末也得加班),有很多工作要完成,因为Warcraft II的游戏引擎基本上得从系统层面返工。大家故意不按日程办事(包括我自己),所以最后游戏延期了超过一年。(不清楚的可以看参考之前的文章。)

  最开始的时候,我并不是StarCraft开发团队的一部分,但在Diablo发布后,StarCraft获得了更多的人力资源,于是我加入了进来。但由于没给我安排固定的任务,我只有自己“使用武力”来驱动项目进展。

  我打算实现一些有意思的功能,比如AI,但AI主要还是Bob Fitch在做。其中一个功能是系统需要判定哪里是最适合聚集武装的地方,AI部队会在那里集结并防守或者准备区域进攻。幸运的是,已经有成熟的API供我调用了,我可以直接使用路径寻找算法查询哪块地图区域是结合在一起的,以及敌人会在哪里集结重兵、准备进攻,以及加强易被突破区域的布兵情况。

  我重新实现了某些组件,包括之前Craft系列延续的“战争迷雾”系统。StarCraft需要拥有比Warcraft II更好的战争迷雾系统,因为地图的分辨率更高了。所以我们打算实现视线计算,位置更高的单位将会获得更好的使用,同时也增加了游戏战术的复杂度:如果你不知道对手在做什么,想要赢就变得更加困难。同样,躲在角落里的单位也将不会被外面的人看见。

  新的战争迷雾系统是StarCraft项目中最令我感兴趣的地方,我需要做一些快速学习来保证系统功能实现和快速运行。上一个程序员的成果让我很不开心,运行起来非常之慢导致游戏几乎无法运行。我学习了纹理滤波算法和Gouraud描影,最终写出了我职业生涯中最好的x386汇编程序——几乎是现代游戏开发必备的技术。和大家一样,我也希望StarCraft最终能够开源,这样我就能看到自己最喜欢的编码成果,不过我记忆中的代码也许要更好!

  但我在StarCraft的开发中最大的贡献在于修补bug。因为大家都在透支着自己的极限来编写代码,以至于整个开发过程都穿插着bug:每向前两步都会倒退一步。大多数团队成员都在做功能开发,所以我不得不花费大量时间来解决QA(Quality Assurance,质量保证)团队捕捉到的问题。

  高效修复bug的诀窍在于探索可靠地重现这个问题的方法。一旦你知道如何重现一个bug,就很容易分析bug出现的原因,通常离bug修复就不远了。不幸的是,重现“will o’ the wispbug”这样偶尔才出现一次的bug需要几天甚至几周的努力。更糟的是,因为很难甚至不能提前预估修复一个bug会花多长时间,这又会在会议日程上花费更多时间。我说得最多的一句话是“嗯,还在找”。通常我会从早晨开始办公,然后整天都在做bug修复,有时候一天能修复数百个,有时候一个都解决不了。

  有一天我正在检查一段无法运行的代码:我们本希望它能按游戏单位类型选择行为(“采伐单位”、“飞行单位”、“地面单位”等等)和状态(“活动的”、“伤残的”、“受攻击”、“繁忙的”、“闲置的”)。因为时间太过久远,我记不清具体的细节了,有几行代码可能是这样的:

  1. if (UnitIsHarvester(unit)) 
  2.     return X; 
  3. if (UnitIsFlying(unit)) { 
  4.     if (UnitCannotAttack(unit)) 
  5.         return Z; 
  6.     return Y; 
  7. ... 
  8. if (! UnitIsHarvester(unit)) 
  9.     return Q; 
  10. return R;   <<< BUG:永远不会执行到这行代码

  在观察这个问题几个小时后,我猜测可能是编译器bug引起的,于是我又开始查看汇编代码。

  对于非程序员来说,编译器只是将程序员编写的代码转换成可以由CPU直接执行的机器语言的工具。

  1. // Add two numbers in C, C#, C++ or Java  
  2. A = B + C  
  3. ; Add two numbers in 80386 assembly  
  4. mov     eax, [B]    ; move B into a register  
  5. add     eax, [C]    ; add C to that register  
  6. mov     [A], eax    ; save results into A


31/3123>

评 论

论坛新帖



建议使用IE 6.0以上浏览器,800×600以上分辨率,法律顾问:上海信义律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2022, 沪ICP备05003035号
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪公网安备 31010102002173号

51Testing官方微信

51Testing官方微博

扫一扫 测试知识全知道