48小时游戏开发冠军时有大量bug为什么能够编译

51CTO旗下网站
iOS开发中,如何合理地制造“BUG”并且查找BUG
可能在平时的编程实践中,往往简单的把BUG与Crash基本等价了。而且我们很多精力也都放在解决Crash的Bug上面。而对于没有Crash 掉的BUG,似乎没有过多的关注。但是,实际情况上那些让人痛彻心扉的“天坑”往往是那些没有Crash掉的BUG造成的,比如前一段时间OpenSSL 心脏大出血。为什么这么说呢?且听我慢慢道来。
作者:佚名来源:blog.jobbole| 10:54
什么是BUG,简单点说就是,程序没有按照我们预想的方式运行。我比较喜欢把BUG分成两类:
没有Crash掉的
可能在平时的编程实践中,往往简单的把BUG与Crash基本等价了。而且我们很多精力也都放在解决Crash的Bug上面。而对于没有Crash 掉的BUG,似乎没有过多的关注。但是,实际情况上那些让人痛彻心扉的&天坑&往往是那些没有Crash掉的BUG造成的,比如前一段时间OpenSSL 心脏大出血。为什么这么说呢?且听我慢慢道来。
如何合理的制造BUG
Crash掉的BUG,用程序的死证明了你的程序存在问题,你必须抓紧时间来解决程序的问题了。而没有Crash掉的Bug,像是一个善于撒谎的 人,伪装成可以正常运转的样子,让整个程序运行在一个不稳定的状态下。虽然外表看起来好好地(没有crash),但是里子早就烂透了,一旦报露出问题往往 是致命的,比如OpenSSL的心脏大出血。这就是前人总结的&死程序不说谎&。
Crash不可怕,可怕的是程序没有Crash而是运行在一个不稳定的状态下,如果程序还操作了数据,那带来的危害将是灾难性的。
所以放心的让程序Crash掉吧,因为当他Crash掉的时候,你还有机会去修正自己的错误。如果没有Crash,那就有可能要给整个程序和产品收 尸了。因此合理制造&BUG&的原则之一,也是最大的原则就是:尽量制造Crash的BUG,减少没有Crash的BUG,如果有可能将没有Crash掉 的Bug转换成Crash的BUG以方便查找。
这个应该都比较熟悉,他的名字叫做&断言&。断言(assertion)是指在开发期间使用的、让程序在运行时进行自检的代码(通常是一个子程序或 宏)。断言为真,则表明程序运行正常,而断言为假,则意味着它已经在代码中发现了意料之外的错误。断言对于大型的复杂程序或可靠性要求极高的程序来说尤其 有用。而当断言为假的时候,几乎所有的系统的处理策略都是,让程序死掉,即Crash掉。方便你知道,程序出现了问题。
断言其实是&防御式编程&的常用的手段。防御式编程的主要思想是:子程序应该不因传入错误数据而被破坏,哪怕是由其他子程序产生的错误数据。这种思 想是将可能出现的错误造成的影响控制在有限的范围内。断言能够有效的保证数据的正确性,防止因为脏数据让整个程序运行在不稳定的状态下面。
关于如何使用断言,还是参考《代码大全2》中&防御式编程&一章。这里简单的做了一点摘录,概括其大意:
1. 用错误处理代码来处理预期会发生的状况,用断言来处理绝不应该发生的状况。
2. 避免把需要执行的代码放到断言中
3. 用断言来注解并验证前条件和后条件
4. 对于高健壮性的代码,应该先使用断言再处理错误
5. 对来源于内部系统的可靠的数据使用断言,而不要对外部不可靠的数据使用断言,对于外部不可靠数据,应该使用错误处理代码。
而在iOS编程中,我们可以使用NSAssert来处理断言。比如:
-&(void)printMyName:(NSString&*)myName&&{&&&&&&NSAssert(myName&==&nil,&@&名字不能为空!&);&&&&&&NSLog(@&My&name&is&%@.&,myName);&&}&
我们验证myName的安全性,需要保证其不能为空。NSAssert会检查其内部的表达式的值,如果为假则继续执行程序,如果不为假让程序Crash掉。
每一个线程都有它自己的断言捕获器(一个NSAssertionHanlder的实例),当断言发生时,捕获器会打印断言信息和当前的类名、方法名等信息。然后抛出一个NSInternalInconsistencyException异常让整个程序Crash掉。并且在当前线程的断言捕获器中执行handleFailureInMethod:object:file:lineNumber:description:以上述信息为输出。
当时,当程序发布的时候,不能把断言带入安装包,你不想让程序在用户机器上Crash掉吧。打开和关闭断言可以在项目设置中设置:
在release版本中设置了NS_BLOCK_ASSERTIONS之后断言失效。
尽可能不要用Try-Catch
并不是说Try-Catch这样的异常处理机制不好。而是,很多人在编程中,错误了使用了Try-Catch,把异常处理机制用在了核心逻辑中。把其当成了一个变种的GOTO使用。把大量的逻辑写在了Catch中。弱弱的说一句,这种情况干嘛不用ifelse呢。
而实际情况是,异常处理只是用户处理软件中出现异常的情况。常用的情况是子程序抛出错误,让上层调用者知道,子程序发生了错误,并让调用者使用合适的策略来处理异常。一般情况下,对于异常的处理策略就是Crash,让程序死掉,并且打印出堆栈信息。
而在iOS编程中,抛出错误的方式,往往采用更直接的方式。如果上层需要知道错误信息,一半会传入一个NSError的指针的指针:
-&(void)&doSomething:(NSError*&__autoreleasing*)error&{&&&&&...&&&&&if(error&!=&NULL)&&&&&{&&&&&&&&&*error&=&[NSError&new];&&&&&}&&&&&....&}&
而能够留给异常处理的场景就极少了,所以在iOS编程中尽量不要使用Try-Catch。
(PS:见到过使用Try-Catch来防止程序Crash的设计,如果不是迫不得已,尽量不要使用这种策略)
尽量将没有Crash掉的BUG,让它Crash掉
上面主要讲的是怎么知道Crash的&BUG&。对于合理的制造&BUG&还有一条就是尽量把没有Crash掉的&BUG&,让他Crash掉。这 个没有比较靠谱的方法,靠暴力吧。比如写一些数组越界在里面之类的。比如那些难调的多线程BUG,想办法让他Crash掉吧,crash掉查找起来就比较 方便了。
总之,就是抱着让程序&死掉&的心态去编程,向死而生。
如何查找BUG
其实查找BUG这个说法,有点不太靠谱。因为BUG从来都不需要你去找,他就在那里,只增不减。都是BUG来找你,你很少主动去找BUG。程序死 了,然后我们就得加班加点。其实我们找的是发生BUG的原因。找到引发BUG的罪魁祸首。说的比较理论化一点就是:在一堆可能的原因中,找到那些与BUG 有因果性的原因(注意,是因果性,不是相关性)。
于是解决BUG一般可以分两步进行:
合理性假设,找到可能性最高的一系列原因。
对上面找到的原因与BUG之间的因果性进行分析。必须确定,这个BUG是由某个原因引起的,而且只由改原因引起。即确定特定原因是BUG的充分必要条件。
找到原因之后,剩下的事情就比较简单了,改代码解决掉。
合理性假设
其实,BUG发生的原因可以分成两类:
我们自己程序的问题。
系统环境,包括OS、库、框架等的问题。
前者找到了,我们可以改。后者就比较无能为力了,要么发发牢骚,要么email开发商,最后能不能被改掉就不得而知了。比如iOS制作framework的时候,category会报方法无法找的异常,到现在都没有解决掉。
当然,一般情况下导致程序出问题的原因的99.999999%都是我们自己造成的。所以合理性假设第一条:
首先怀疑自己和自己的程序,其次怀疑一切。
而程序的问题,其实就是开发者自己的问题。毕竟BUG是程序员的亲子亲孙,我们一手创造了BUG。而之所以能够创造BUG,开发者的原因大致有三:
知识储备不足,比如iOS常见的空指针问题,发现很多时候就是因为对于iOS的内存管理模型不熟悉导致。
错心大意,比较典型的就是数组越界错误。还有在类型转化的时候没注意。比如下面这个程序:
&for&(int&i&=&100;&array.count&-&(unsigned&int)i&&&10&;&)&{&&&&&i++&&&&&.....&}&
按道理讲,这应该是个可以正常执行的程序,但是你运行的话是个死循环。可能死循环的问题,你改了很多天也没解决。直到同事和你说array.count返回的是NSUInterge,当与无符号整形相间的时候,如果出现负值是回越界的啊。你才恍然大悟:靠,类型的问题。
这个就是思维方式的问题,但是也是问题最严重的。一旦发生,很难查找。人总是最难怀疑自己的思维方式。比如死循环的问题,最严重的是函数间的循环引用,还有多线程的问题。
但是庆幸的是绝大多数的BUG都是由于知识储备不足和粗心大意造成的。所以合理性假设的第二条:
首先怀疑基础性的原因,比如自己知识储备和粗心大意等人为因素,通过这些原因查找具体的问题。之后再去怀疑难处理的逻辑错误。
有了上面的合理性怀疑的一些基本策略,也不能缺少一些基本的素材啊。就是常见的Crash原因,最后我们还是得落地到这些具体的原因或者代码上,却找与BUG的因果性联系。
访问了一个已经被释放的对象,比如
NSObject&*&aObj&=&[[NSObject&alloc]&init];&[aObj&release];&NSLog(@&%@&,&aObj);&
访问数组类对象越界或插入了空对象
访问了不存在的方法
字节对齐,(类型转换错误)
多线程并发操作
Repeating NSTimer
合理性假设第三条:尽可能的查找就有可能性的具体原因。
因果性分析
首先必须先说明的是,我们要找的是&因果性&而不是&相关性&。这是两个极度被混淆的概念。而且,很多时候我们错误的把相关性当成了因果性。比如, 在解决一个多线程问题的时候,发现了一个数据混乱的问题,但是百思不得其解。终于,有一天你意外的给某个对象加了个锁,数据就正常了。然后你就说这个问题 是这个对象没有枷锁导致的。
但是,根据上述你的分析,只能够得出该对象枷锁与否与数据异常有关系,而不能得出就是数据异常的原因。因为你没能证明对象加锁是数据异常的充分必要 条件,而只是使用了一个单因变量实验,变量是枷锁状态,取值x=[0,1],x为整形。然后实验结果是枷锁与否与数据异常呈现正相关性。
相关性:在概率论和统计学中,相关(Correlation,或称相关系数或关联系数),显示两个随机变量之间线性关系的强度和方向。在统计学中,相关的意义是用来衡量两个变量相对于其相互独立的距离。在这个广义的定义下,有许多根据数据特点而定义的用来衡量数据相关的系数。
因果性:因果是一个事件(即&因&)和第二个事件(即&果&)之间的关系,其中后一事件被认为是前一事件的结果。
错误的把相关性等价于因果性。不止是程序员,几乎所有人常见的逻辑错误。为了加深认识,可以看一下这篇小科普:。
因果性分析的首要问题就是,别被自己的逻辑错误欺骗,正确的分辨出相关性和因果性之间的区别。不要把相关性等价于因果性。
之后便是因果性分析的内容了,之前一直反复说,因果性分析的目的就是确定特定原因是BUG发生的充分必要条件。那么确定这个事情,就需要两步:
充分性证明
必要性证明
关于充分性证明,这个基本上就是正常的逻辑推理。基本思路就是,能够还原出BUG出现的路径,从原因到BUG发生处的代码,走了怎样的函数调用和控制逻辑。确定了这个基本上就能够证明充分性。一般情况下根据Crash的堆栈信息能够,非常直接的证明充分性。
关于必要性证明,这个就比较困难了。充分性和必要性的定义如下:当命题&若A则B&为真时,A称为B的充分条件,B称为A的必要条件。那么必要性就 是,BUG能够作为导致BUG的原因的原因。这个说法比较拗口。换种说法,就是你得确认这个BUG能够解释原因,这个BUG就是而且只是这个原因造成的。
只有证明了充分必要性,才能算是真正找到了BUG的原因。
【编辑推荐】
【责任编辑: TEL:(010)】
大家都在看猜你喜欢
头条头条关注头条热点
24H热文一周话题本月最赞
讲师:207533人学习过
讲师:145356人学习过
讲师:15524人学习过
精选博文论坛热帖下载排行
有些网站看起来很清爽;
有些网站看起来很杂乱;
有些网站能让你轻松地找到资料;
有些网站让你犹如置身迷宫……
订阅51CTO邮刊为什么游戏漏洞要叫做BUG_百度知道
为什么游戏漏洞要叫做BUG
经常听朋友说BUG但不知道为什么这么叫,怎么不说是别的而说是BUG?
我有更好的答案
就是不允许用户做非法的操作。软件的错误全是厂家设计错误,在中文里面,引得一只小虫子,是指电脑系统的硬件,比如本来是做加法但按了减法键。这样用户会得到一个不正确的结果,但不会引起bug发作?Bug、缺陷或问题?钻进了一支真空管内、系统软件(如操作系统)或应用软件(如文字处理软件)出错。机房是一间第一次世界大战时建造的老建筑,并注明“第一个发现虫子的实例。”[1] 从此以后,人们将计算机错误戏称为虫子(bug),导致整个计算机无法工作。研究人员费了半天时间,总算发现原因所在,是软件厂商不负责的胡说八道。只要允许用户做的,都是合法的。用户根本就没有办法知道厂家心里是怎么想的,一是硬件部件老化失效等,编译器的发明者格蕾斯·哈珀(GraceHopper)发现的,把这只小虫子从真空管中取出后,计算机又恢复正常,下午三点。哈珀中尉正领着她的小组构造一个称为“马克二型”的计算机。这还不是一个完全的电子计算机。后来,Bug这个名词就沿用下来,哪些操作序列是非法的。 从电脑诞生之日起,就有了电脑BUG。但是现在,在电脑系统或程序中,如果隐藏着的一些未被发现的缺陷或问题,最后定位到第70号继电器出错。哈珀观察这个出错的继电器。 与Bug相对应,人们将发现Bug并加以纠正的过程叫做“Debug”,意即“捉虫子”或“杀虫子”。遗憾的是,它使用了大量的继电器,一种电子机械装置,房间没有空调,所有窗户都敞开散热。 突然,马克二型死机了。技术人员试了很多办法,至今仍没有与“Bug”准确对应的词汇,于是只能直接引用“Bug”一词。虽然也有人使用“臭虫”一词替代“Bug”,但容易产生歧义。第一个有记载的bug是美国海军的编程员,所以推广不开。 所谓“(Bug)”,用透明胶布帖到“事件记录本”中,发现一只飞蛾躺在中间,已经被继电器打死。硬件的出错有两个原因,一是设计错误。那种说用户执行了非法操作的提示,人们也叫它“Bug”,这是怎么回事呢? 原来,第一代的计算机是由许多庞大且昂贵的真空管组成。软件厂商在设计产品时的一个基本要求,领导了著名计算机语言Cobol的开发。 日。哈珀后来成了美国海军的一个将军。第二次世界大战还没有结束。哈珀的小组日以继夜地工作。那是一个炎热的夏天。她小心地用摄子将蛾子夹出来我给你解释下吧 原来我参加过游戏漏洞的测试 所以做了点笔记!! 其实它的中文名称就是漏洞啊 不管什么领域Bug一词的原意是“臭虫”或“虫子”,表示电脑系统或程序中隐藏的错误。用户可能会执行不正确的操作,并利用大量的电力来使真空管发光。可能正是由于计算机运行产生的光和热
在新窗口中选择“关闭Wi-Fi”,在完成关闭操作后://vip9904。第二招.baidu&#47,即可重启Wi-Fi连接:忽略网络如果上面的做法没有起作用的话,就应该选择让安卓设备忽略该网络,并重新进行添加操作。移动到需要忽略网络的覆盖范围之外。这样安卓手机就应该可以获得新的地址,选择忽略该网络,它会被应用到当前Wi-Fi中,如果没有出现地址冲突?jsher第一招:关闭并重启Wi-Fi连接超好玩gft,重新进入该项目,返回到覆盖范围之中,就不用担心.
BUG是漏洞的英语简写.
为您推荐:
其他类似问题
换一换
回答问题,赢新手礼包
个人、企业类
违法有害信息,请在下方选择后提交
色情、暴力
我们会通过消息、邮箱等方式尽快将举报结果通知您。您的位置:
本文网址:
共有:条评论信息评论信息
Copyright &
Inc. All rights reserved.中国工业和信息化部备案号:
页面执行时间1.2969 s《X重生》开发商为游戏中大量BUG道歉
作为系列的第六款游戏,《X重生》延续了系列在发售时满是BUG的传统。BUG的情况是在太严重,让Egosoft的总监Bernd Lehahn也不得不在他们的论坛上公开道歉。在一个帖子中,他谈到了游戏目前的一些问题,同时也公布了游戏未来升级的计划。
《X重生》开发商为游戏中大量BUG道歉
Lehahn写到:“我想对遇到技术问题的玩家表示歉意。我已经在Steam的论坛上发了一个帖子,在帖子中我列举了最普遍的错误,而且现在我们也收集了大量的信息。”
在另外一个帖子中,Lehahn列举了目前避免司机和提高游戏性能的建议。他同时也提到了一些他们正在尝试修复的Bug,其中包括一个让飞船可以穿过空间站的Bug。
工作室还在努力为以后加入新的游戏内容而努力,明年初可能会放出一个大型的升级补丁。而在这之前,他们将会提供小型的升级补丁,来改善NPC,菜单和加入键位绑定等。
更多精彩游戏内容,请点击【】阅读 (28635) 评论 (59)
阅读 (21646) 评论 (8)
阅读 (21106) 评论 (6)
阅读 (40143) 评论 (5)
阅读 (31640) 评论 (4)
阅读 (28702) 评论 (7)
Advertisment ad adsense googles cpro.baidu.com

我要回帖

更多关于 48小时游戏开发冠军 的文章

 

随机推荐