晓晓
2018-03-13
来源 :网络
阅读 1475
评论 0
摘要:什么样的 BUG 会让你目瞪口呆?
是这样的,我叫--,
曾经我想注册一个新浪微博的账号,起昵称的时候出现了这样的事……
起初我以为只不过是重名,这个名字已经被抢注了……
后来发现这事没这么简单……我这名字简直跟某邪教组织词汇和国家领导人是一个级别的……
到最后才发现,比脏话的屏蔽等级还要高……
上图……


刚刚我又登陆微博试了一下……结果……

我们围绕bug这一让程序员终生虐心的内容发起了一次讨论:
您遇到过何种奇葩的BUG?
有什么虐心的BUG?
抓狂的BUG?
一起来看看社区网友们都遇到过哪些让人目瞪口呆的bug吧:
社区昵称:数据使命
回想起这个bug,仍然让我有些痛苦。作为一个程序员,在发现bug时,你学会了首先在自己代码中找问题,或许在测试一万次之后,你会把问题归咎于编译器。只有在这所有的都不起作用之后,你才会把问题归咎于硬件。
这是我遭遇一个硬件bug的故事。
抛开别的不说,我曾为《Crash Bandicoot》写存储卡(读写)代码。对于一个自大的游戏程序员,这就像是在公园里散步一样轻松愉快,我认为只要几天就写完了,最终调试用了六个礼拜。在此期间我做一些其他的事情,但我一直回来处理这个bug——几天内每天几个小时。这个bug实在烦人。
这个bug的症状是,当你需要保存你的进度时,代码会访问存储卡,而大部分情况下没有什么问题…但是偶尔读写会超时…没有任何明显的原因。一个短小的写入经常毁掉存储卡。玩家要保存进度,我们不仅不保存,还擦除他们存储卡上的全部东西。天哪。
过了一段时间,我们在Sony的制作人Connie Booth慌了。我们显然不能带着这个bug发布游戏,而六个星期之后我对于问题出在哪一点线索都没有。通过Connie我们向其他 PS1 开发者求助:有没有人出现过像我们这样的情况?没有。绝对没有任何人在存储卡系统上出现任何问题。
在你绞尽脑汁之后,你能做的唯一一个调试方法就是分而治之:一点点去除程序中的代码,直到留下的代码很少但你仍然出问题。像木雕一样去除没有问题的代码,留下的就是你的bug所在。
在这样的背景下挑战在于,视频游戏是很难去除某一部分的。在你删除模拟重力或者显示字符的代码后,如何运行游戏?
你必须做的是用一个假装做真正的事情,但实际上只是做很简单的不会出现bug事情的东西来替换掉整个模块。你必须写新的支撑代码来让这些玩意正常工作。这是一个缓慢而痛苦的过程。
长话短说:我做完了。我移除了大片大片的代码,相当多,只留下了初始化代码——就是准备游戏运行系统,初始化底层硬件等等。当然,我不能显示加载/保存菜单,因为我截除了所有的图像代码。但是我能够假装用户使用(不可见的)加载/保存屏幕并且请求保存,然后写入卡中。
我最终以一个带有这个bug的很少量的代码结束——但问题仍然随机出现!在大多数情况下没啥问题,但是偶尔会失效。基本上所有的Crash的实际代码都被移除了,但还是这样。这实在是莫名其妙:留下来的代码基本上都没做什么事。
在那时——估计是凌晨3点——一个想法蹦了出来。读写(I/O)涉及精确定时。无论是硬盘、存储卡、蓝牙发送器——随便啥——做读写的底层代码都是根据时钟来的。
时钟让不直接连接到CPU的硬件设备和cpu运行的代码同步。时钟决定了波特率——数据从一头传到另一头的速率。如果计时有什么问题,硬件或者软件或者两者都会乱七八糟的。这真的,真的很糟糕,并且通常导致数据损坏。
如果我们的初始化代码以某种方式弄乱了计时会怎么样?我又看了一遍测试程序中和计时有关的代码,并注意到我们将PS1上的可编程计时器设置到了1kHz(1000跳每秒)。这是比较快了,当PS1启动的时候,默认状态大概是100Hz。因此,大多数游戏将他们的计时器设置为100Hz。
这个游戏的带头(和除我外的唯一)开发者Andy,将计时器设置为1kHz,使得Crash的动作计算更加准确。Andy喜欢矫枉过正,如果我们要模拟重力,我们应该尽可能的提高精度!
然而如果提高计时器频率莫名其妙的干扰了整个程序的计时,故而将这个计时器设置到存储卡的波特率上会怎样呢?
我将计时器代码注释掉。然后我就无法复原这个bug了。但是这并不表示bug被修复了,这个问题是随机发生的。万一我只是运气好呢?
几天过去了,我还是在玩我的测试程序。Bug没有再出现。我回到全部的Crash代码中,修改了加载/保存代码,在访问存储卡之前将可编程计时器重置为默认设置(100Hz),之后设置回1kHz。从此之后没有发现问题再次出现。
但是…为什么?
我重新回到测试程序上,试着检测当计时器设置为1kHz时出现的那些错误的模式。终于,我注意到这些错误出现在使用PS1手柄的人身上。因为我自己很少这样做,所以我没有注意到(为啥我要在测试加载/保存代码的时候用手柄)。但是有一天我们的美工等我去完成测试(我确定那时候我在爆粗口),而他紧张的摆弄着手柄。卡损坏了。“等下,怎么回事?喂,再来一次!”
一旦我发现了这两件事是联系着的,就很容易重现bug:开始写入存储卡,动一下手柄,存储卡损坏。在我看来完全是硬件bug。
我去找Connie告诉他我的发现。她转述给设计过PS1的硬件工程师。她被告知:“不可能,这不可能是硬件问题。”我跟她说问一下我能不能直接和他说。
那个工程师给我打电话了,他用着他的烂英语,我用着我更烂的日语,我们争论一会。我最后说:“我给你一个30行的测试程序,让你在动手柄的时候能够出现这问题。”他答应了。他向我保证,这是浪费时间,而他正在一个新项目上很忙,但因为我们是Sony很重要的开发者,他会试的。
第二天晚上(我们在洛杉矶,而他在东京,所以对于我来说是晚上而他是到了第二天),他给我打电话,不好意思的向我道歉。这是个硬件问题。
我还是没有完全搞清楚问题到底在哪,但是我的印象中,从Sony总部的反馈听到的是,如果将可编程计时器设置到足够高的时钟频率,会影响到主板上时钟晶振附近的一些东西。这些东西之一就是存储卡的波特率控制器,同时也设置手柄的波特率。我不是搞硬件的,所以对于细节我相当模糊。
但是主旨是主板上两个独立部分的串扰,以及手柄接口和存储卡接口数据发送的结合在 1kHz 的时钟频率下会导致丢位,从而数据丢失,以致卡损坏。
这是我全部编程生涯中,唯一一次因为量子力学而debug的问题。
社区昵称:巴洛克上校
我遇到的一个百度的彩蛋但是我认为他就是一个大BUG,昨天我想要找一张打雷闪电的照片于是在百度上输入了打雷二字,此时我正带着耳机但是没放音乐至于原因。。。。;就当我聚精会神的找东西的时候,只听耳机里突然轰隆一声巨响,这家伙给我吓了一大跳,鼠标差点让我扔了,看了一眼旁边同事正用怪异眼光看着我。。。。。。(这东西应该是那个调皮的程序员搞的恶作剧,还好我没心胀病要不底吓个好歹的)后来上网一查不如输入布谷鸟 黑洞 大风 换转 duang 海边 都有变换以前一直都没发现过;
之前还玩过一个联想的游戏类似微信的飞机大战,用手机玩几乎几下就Game Over 但是我发现用平板玩只要你想玩你就不会死,于是赶在周日我就用平板完了一整天连饭都没吃玩了13个小时,登上那个榜首可就在公布结果发奖时竟说我作弊取消资格,结果和他们好顿理论才恢复。(其实很多HTML5新游戏都是用平板玩很轻松)
还有mac版的优酷在看视频时候如果切换清晰度有70%的概率会直接崩溃
ios的通知栏在不特定情况下收到通知后,下拉通知栏里面所有的内容通通消失
社区昵称:szm.
最神奇的bug就是百度的验证码了,只要他出验证码,我就没输入对过??明明输入的是对的,却一直提示验证码输入错误,还好很多时候登录非刚需。
另一个bug是新浪的,之前它推出微盾,于是绑了账号,某一天手机恢复出厂设置,于是悲剧了,登录账号需要微盾验证码,还是非定期出现,有时候会让输,有时候直接可进入,注册时的手机号也没了,基本上这个号废了,可惜了。
淘宝也有bug,为啥我买了一件商品后给我推荐更便宜,看起来更好的商品,你这样良心不会痛么。
社区昵称:机器的心脏

昨晚刷的第二版,浏览器主页中间有个搜索栏,一直到今天下午都有,今晚打开浏览器不见了。。我记得之前更新第一版之后也有过这个情况。。
然后今晚重启之后桌面边缘出现个诡异的百度输入法图标,轻按它可以上下拖动,但往中间一拉就消失,只是锁屏又解锁之后又会出现。 如果重按住它,还会有一次震动感,然后居然可以拖着它满屏跑,放手它就自己缩回屏幕边缘——简直就像个电子宠物。。真是个诡异的Bug...

社区昵称:雪雪雪雪儿
在 2000 年的时候,项目组负责有关 JPEG 文件格式的工作,被称为 JPEG 小组,当时决定推出一个叫做 JPEG2000 的新版本。新版本有着很多很棒的想法,其中有一点是它支持流媒体图像。一张 JP2 图像可以包含多种分辨率,并且按照分辨率由低到高排列。所以,在你下载图片的时候,可以很快速的获取低分辨率的图片。这种特性的好处是,在网络状况很不好的情况下,浏览器可以迅速优先加载低分辨率的图像。同时,低分辨率的设备在匹配到适合它分辨率的图像后就会停止下载。
当时,JPEG2000 希望 JP2 图像标准可以被加入到浏览器中(剧透一下:很可惜,并没有)。我们想要用它来构建地图类的应用。JP2图像可以编码卫星图片,并且我们专门返回SVG地图的服务器。由于没有浏览器支持JP2,我创建了一个ActiveX控件,用来将JP2图像以流的形式转化为SVG地图。这真是太酷了,(在当时)我们的图像分辨率可是Google地图的十倍。
我用的是一个叫做 Kakadu 的第三方库。这是一个能够解析和将JP2 图像转化为流的开源库。Kakadu 的表现真的非常非常棒! 它非常快!除了在使用一段时间后它会无征兆地卡住。这引起了我的注意,并且我怀疑问题产生的原因是用于存在线程竞争。所以,我决定通过 debug 来解决这个问题。在当时,我很年轻,而且对多线程的理解还算不错,但我还没有真正解决过一个多线程问题,是的,对此我很兴奋。
所以我通过深入它们的源码来开始调试。我记得在一开始开启debug进行调试的时候,问题竟然消失了。该死!事实上,调试器本身作为一个同步机制,它改变了线程中指令的执行时间。
于是我开始添加log日志输出来观察一下。在我添加log之后,问题竟然又一次消失了,我的天!由于日志信息记录到文件系统,文件系统作为一个同步机制再一次改变了指令的执行时间。
调试不行,添加log日志也不行。我还没有告诉你,这是一个多么复杂的大工程,所以,在我解决这个问题之前,我需要弄清楚如何在多线程环境中解决问题,该死!
于是,我开始思考,这会是由于同步机制以外的代码而导致代码的执行时间被修改么?所以说,只要我保持内外部代码一致同步,那我就有可能阻止执行时间被修改。于是,我开始尽量的减少log日志输出。最后,我懂了,如果我输出一个字符的log日志就不会出错,也就是说,log日志最多不能超过一个字符。
所以,第一件我需要弄清楚的事是,问题的发生与否是不是由于执行了不同的代码所导致的。要记住,最多我只能输出单个字符的log日志。于是,我开始深入分析每一段代码,而不是仅仅理解它的作用。每当我到达一个条件判断语句时,我会在两条分支上分别输出日志信息。其中一条分支输出“”,另一条分支输出“/”。当我看到一个循环语句时,我在循环体内输出“|”。当我看到输出的日志时,它是这个样子的
|||//|||||||||//
我会在运行程序的时候,分别记录下代码执行成功与失败两种情况下的字符串信息。下一步,比较两个字符串,找出不同的地方。最后,我会根据字符串信息中不同的地方,对应到代码中去进一步分析。
因为我不能输出过多的日志信息,所以我不得不仔细分析。幸运的是,Kakadu的代码结构非常好。我真想亲一口Kakadu的开发者(虽然他们制造了这个bug)。所有的代码层次结构都很清晰。它们通过高级方法来调用底层的方法。所以,我选择在高级方法中添加单字符log信息。当我找到差异时,通过代码我可以知道产生差异的原因。在大多数情况下,差异都是由于底层调用的方法不同而产生的。于是,我删除掉原有的log日志,然后在底层的方法中添加相同的log日志来观察,就这样,一层又一层,直到我找到产生bug的原因所在。
这整个过程花了大约三个星期。最后通过修改了一个字符解决了问题。由于渲染线程在等待生产者线程加载的数据,而形成一个循环等待,造成了卡死的问题。计数器在判断数据时,使用的是<而不是<=。通常,计数器会从预期的情况中,得到想要的数据,并且能够正常执行。在极少数情况下,当=条件满足时,渲染线程会过早的解析数据,造成异常,并跳出执行语句。从而导致渲染线程中断执行。
本文由职坐标整理并发布,希望对同学们有所帮助。了解更多详情请关注职坐标软件测试之测试管理频道!
喜欢 | 0
不喜欢 | 0
您输入的评论内容中包含违禁敏感词
我知道了

请输入正确的手机号码
请输入正确的验证码
您今天的短信下发次数太多了,明天再试试吧!
我们会在第一时间安排职业规划师联系您!
您也可以联系我们的职业规划师咨询:
版权所有 职坐标-一站式AI+学习就业服务平台 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
沪公网安备 31011502005948号