解决bug的技巧

我在知乎上的一个回答:http://www.zhihu.com/question/27044029

我说的可能不是debug,主要是生产环境出问题时的查错。

首先,开发的时候就做好准备。
包括但不限于:
好好记录日志。一定要记录方法的入参、出参、异常信息。
准备好日志下载、分析的工具。必要时候日志拆分、分析脚本要能写出来。

前两天上线时,不停的收到报错邮件。而且邮件里发送来的errmsg居然是null。
当时的debug的关键三步,第一是日志下载。生产环境有比较完善的日志机制,我把报错前一个小时的都扒了下来。第二是日志分析,对比日志流,发现第x行日志打印之后,第x+n行没有打印。于是很清楚的确定,问题就在这n行之内。最后再查看第x行记录的入参数据——入参是个javabean,日志里把其中所有非null的数据都记录了下来。于是很清楚的看到“feeExp=无”。
从日志下载到找到“无”,前后不超过10分钟。
然后我让系统管理员修改了对应的配置数据,都没验证结果就陪媳妇看电影去了。
没然后了,那之后直到现在,只发了一封错误邮件。后面说。

生产环境查错,好的日志真的是关键。曾经翻一份10G+的日志,满篇是“xx方法开始执行”“xx方法执行完毕”,什么数据都没有,真的有提刀砍人的心。

小tip,用log4j记录异常日志的时候,一定要用logger.error("error message in string",exception)这个重载方法。这个方法会把exception的异常信息堆栈一股脑打印出来。虽然不太友好,但是猴哥们应该都知道它的便利性。

在此基础上,如果对系统业务、代码流程熟悉,可以走很大一条捷径。感谢那些好好设计代码结构的人。这样,出问题的时候,有时即使没有日志或者不看日志,也可以很轻松的就把问题锁定在三、四行代码里面。
今天上午收到了另一封报错邮件。这次有errmsg了,是“Integer can not cast into Double”。
因为是我自己写的代码,我对流程非常熟悉,并且我清楚的知道只有一个地方可能产生Integer强转Double——虽然不好意思承认,但确实是开发和测试时考虑不周全导致的。于是再次找管理员确认了一个配置数据,让她把一个“5”改成了“5.00”。再然后,我去写别的代码了。

如果上面的步骤没法查出并解决问题,那么,你得能够重现错误。
这时候一个UAT环境的重要性就凸显出来了。在上家工作的时候,由于是接手别人做了一半的系统,很多时候没日志可查(查了也只会有提刀砍人的冲动)。因此,大多数时候用户报告bug时,我们第一步都是去UAT环境上设法重现。UAT上是开了log4j的debug日志的(生产上考虑硬盘空间和性能原因,最多开到info,有的甚至只有error),有用的信息总比生产上要多一些。而且=。=偶尔出现UAT无法重现的问题,我们会以此为借口告诉用户改不了……
UAT、INT、最后是到自己开发环境上重现,然后修改。

运气好的话,在重现过程中你能看到出错时打印出来的异常堆栈信息。由于没有生产环境那么大的系统压力,这时候就可以细细地慢慢地美美地……咀嚼一下这些信息了。
我以前一直觉得看异常堆栈很简单,以至于跟同事急过眼,得找机会跟人家道歉去=。=刚才尝试整理看堆栈所需的能力(科技树?),发现能轻松看懂堆栈信息的猴哥,绝对不是一个简单的机枪兵或者大G。第一得看得懂英语,或者能借助各类词典看懂那段英语;其次要懂异常机制,得从那一堆的at……和cause by ……中找到需要自己去关注、或者说自己有能力去关注的点;而且常常还得懂一些编译啊classloader啊jvm啊服务器啊相关的东西;好记性或者烂笔头是个优势,因为好多问题会重复出现;此外如果能够拥有脚踏实地的想象力能获得额外加成,因为有些异常信息真的太匪夷所思了。
上上次上线时候,我就遇到了这么个匪夷所思的问题。需要上线的代码在INT环境上跑的非常顺溜,上线的时候报了个NoClassDefFoundError。嘛……英语很好懂,no found的那个类也很清楚的跟在error的后面,但是……INT上真的非常顺溜啊……

这时,如果对系统业务、代码流程熟悉,又可以走很大一条捷径。很多次跟同事一起查错,他们还没看完日志我就猜到问题所在了,基本就是因为我走了这条捷径。

总的来说,我查bug,基本上是依赖程序在运行中留下的信息。大多数是我自己设置的“打卡机”,程序运行到这里就得打一次卡。有些是系统提供的帮助。当然会牺牲一些空间和时间的性能。不过目前来看,大多数是值得的。何况这些数据还可以拿来做点性能分析,甚至大数据分析呢。
借助这些信息,加上自己对系统、代码的掌握,大多数bug都能很迅速地定位、并最终解决。

学计算机的第一天老师就教我,“软件=数据+流程”。我到现在才算有了点切身的体会。日志里记录的是动态的数据,代码记录的是静态的流程。二者到手,bug无忧。

debug这个工具,我在追查生产环境的bug时很少使用。真的,大多数情况下,日志+代码就足够了。
我只有在开发期间,调试一些复杂的算法,或者调试大批量数据时会用。复杂算法是因为我人脑性能低,对代码流程分析不过来。大数据量则是没法对各种数据状态一一去分析。幸运——或者不行——的是,我基本没遇到过多少需要debug的情况。认认真真debug的事儿,做的应该不超过十次。

想了想,多线程并发也许是个不好用日志+代码来分析的东西。不过……我写的多线程……还没查过错……

哈哈一股浓浓的优越感是不是……不过说真的,代码较少出生产bug+出了bug能很快排查并解决,作为一只猴子我真的挺有成就感的

时间: 2025-01-06 02:06:54

解决bug的技巧的相关文章

Jmeter实现登录bugfree、新建bug、解决bug脚本(抓包工具实现)

环境 Chrome jmeter3.1 fiddler4 win7 32位 Linux CentOs6.4 bugfree3.0.1 链接:http://pan.baidu.com/s/1gfHpbpD 密码:wpxj  jmeter3.1软件包 链接:http://pan.baidu.com/s/1miHeNfa 密码:yqlp  fiddler4软件包 如果链接失效,可以自己网上寻找资源,或者加我百度云:天涯咫尺HK 一.打开jmeter.添加线程组.录制控制器.HTTPCookie管理器.

微信各种BUG、技巧汇总

BUG: Android 4.0+微信4.5.1 会导致打开的网页文字非常小重现机型 galaxy s3, 三儿子 iOS6 下改变字号,JS获取的高度还是原始字号的高度 ios微信webview里 iframe 里的 input ,双击之后出不了菜单,导致无法输入 android 2.3+4.5微信webview刷新还没过期css的话,返回200,而不是304 无法打开自定义scheme 例如 <a href="tmt://" /> 公众账号 图文列表不认识中文文件名图片

解决bug:Couldn&#39;t load ClientCore from loader dalvik.system.PathClassLoader

当出现错误: java.lang.UnsatisfiedLinkError: Couldn't load ClientCore from loader dalvik.system.PathClassLoader[DexPathList[[zip file "/data/app/cn.gloud.client-2.apk"],nativeLibraryDirectories=[/data/app-lib/cn.gloud.client-2, /vendor/lib, /system/li

解决Bug:Size of a request header field exceeds server limit

用了cms 发现这玩意真不好,老是有各种奇芭的问题跳出来 有时浏览网页时会出现 Bad Request Your browser sent a request that this server could not understand. Size of a request header field exceeds server limit. 意思为:错误的请求.您的浏览器发送一个请求,该服务器无法理解.一个请求头域的大小超过服务器的限制. 以下是解决方法,不过,我个人感觉,不可能无限制的增大请求

关于linux和linux驱动程序解bug的技巧和思考方法

关于linux和linux驱动程序解bug的技巧和思考方法 解bug三步:1)看log,看现象.2)对比代码分析过程,程序流程,线程.中断.workqueue等各个独立执行体的交互3)调试,加入log.验证. 光看代码只能停留在理论上,一定要亲手调试一下才真正知道.另外对比正常和异常时的行为和log区别,交叉试验,才能发现问题的关键.注意各种调试尝试,各种替换调试,即好的和坏的,好的A和好的C,好的A和坏的D,坏的B和好的C,坏的B和坏的D的交叉调试,才能知道问题所在.另外,需要先写简化代码,验

ios捕获异常并发送图片,便于解决bug

在开发过程中,我们有时候会留下Bug,用户在使用我们的app 的时候,有时会出现闪退,这时候我们能够让用户给我们发送邮件,以让我们开发者更加高速的地位到Bug的所在.以最快的时间解决.同一时候也提高用户体验. 在AppDelegate.m文件里,加入例如以下代码: 01 NSUncaughtExceptionHandler* _uncaughtExceptionHandler = nil; 02 void UncaughtExceptionHandler(NSException *excepti

iOS 之 调试、解决BUG

1. iOS 解决一个复杂bug 之 计分卡 2. iOS 调试 之 打印

关于项目中解决bug的心得

在一个比较大的项目中,二次接手项目的人员往往感觉很头疼,感觉比较茫然,下面是我解决问题的一点小小的经验 一个成熟的项目往往有着很强的逻辑,前端也尽然如此.js面向对象 遍历对象枚举属性,参数的传递 递归调用,解决方法: 1 定位问题,(看看问题出在哪个组件当中 js/ vue/ jsx等) 2 判断组件上下逻辑关系,相互依赖,被依赖,还是common config组件(尽量不要动common组件里面的东西) 3 bug所在位置,function() 是一个很好的解决问题的入口,首先在functi

str_replace() 用法bug和技巧

语法 str_replace(find,replace,string,count) 参数 描述 find 必需.规定要查找的值. replace 必需.规定替换 find 中的值的值. string 必需.规定被搜索的字符串. count 可选.一个变量,对替换数进行计数. 这个我不确定是语法bug还是我写法的问题,当出现匹配字符出现一个在第一匹配选项的时候,会出现不完全匹配的情况,导致匹配出的字符有问题 $list = str_replace(array(0,10,20,30,40), arr