如何定位"无法重现“的问题
2007-11-07 16:06
309 查看
无论对于开发人员还是测试人员,遇到无法重现的bug都是一件极其苦恼的事情,为了逃避责任,各个部门之间会互相推脱,长时间无法解决也会给开发人员很大的压力,然而对于一个工程来说,无法重现的BUG往往是非常严重的问题,因为这种错误被发布到用户的机器上,小概率会被放大非常严重的事故,甚至会变成影响公司声誉的灾难事件。
我曾经看过一些测试人员在对待这类问题上的一些经验,比如如严格版本管理,杜绝个人操作错误,收集用户信息等,但对于开发者来说,处理这种问题却棘手的多,由于软件的复杂性,当程序发生异常的时候,往往离真正引起错误的位置已经相差很远,比如我经历的游戏项目增经遇到这样一个问题,玩家的程序运行一段时间后,会莫名其妙发现背包里的物品少了一个,然后再过一段时间之后程序会出现一个非法内存访问的异常而崩溃,通过分析dump文件发现,程序的一个模块在试图访问一块已经被释放的内存,然而这块内存是如何被操作的则无从查起,更糟糕的是,QA在内网根本无法重现这个这个错误,必须连接上外网正式服务器才会出现,而且必须运行很长时间后才会出现问题。
由于版本已经发布,玩家不断地投诉让老板黑着脸,已经发话让所有的开发人员必须解决完问题才能回家,经过一番折腾,终于发现原因,原来是一个程序员在改进“TransferItem”这个模块时(就是通过聊天信息传送物品)犯了一个愚蠢的错误,会把背包里不该删除的物品删除,留下一个野指针在那里,当别的模块访问背包时就会出现异常,由于跟所在场景的聊天信息量相关,所以只有在玩家接收到足够的聊天信息后才会发生异常,错误解决了,庆幸之余,我又在想,毕竟开发人员的能力参差不齐,我们可能无法杜绝这种错误的再次出现,那有没有方法能更快的发现这种错误呢。
其实我曾经设想过,如果把我们的程序能够基于一种“可重现”模型的话,问题就会容易的多。
什么是“可重现”模型呢,简单的说,我们的程序可以看作一个盒子,它接收的输入无非就是玩家的操作(鼠标,键盘),网络消息包,窗口消息等,如果我们能把这些输入都记录下来,是不是意味着我们就能够一模一样的重现任何问题呢?
![](http://122.img.pp.sohu.com/images/blog/2007/10/28/14/26/11680c74b2f.jpg)
然而,事实上并不是这么简单,我们的程序还会调用一些其他系统的函数,比如我们会调用Api获得系统时间,会调用C运行时库获得一个随机数,会调用DirectX接口渲染等,运行环境的不同也会使我们的程序走不同的逻辑代码,最简单的例子,程序运行在一台烂机器上会导致两帧之间时间差变大,而这个时间差会导致我们的程序在运行时行为不一致,甚至走不同的switch/case,这是个难解决的问题,但我们并非需要严格意义上的重现,大部分时候记录输入已经足够能帮助我们找到问题了,比如上面举的例子,当时我就是记录下所有接收到的网络消息,然后让逻辑顺序执行,结果重现了这个问题,才最终定位错误的根源的。
我曾经看过一些测试人员在对待这类问题上的一些经验,比如如严格版本管理,杜绝个人操作错误,收集用户信息等,但对于开发者来说,处理这种问题却棘手的多,由于软件的复杂性,当程序发生异常的时候,往往离真正引起错误的位置已经相差很远,比如我经历的游戏项目增经遇到这样一个问题,玩家的程序运行一段时间后,会莫名其妙发现背包里的物品少了一个,然后再过一段时间之后程序会出现一个非法内存访问的异常而崩溃,通过分析dump文件发现,程序的一个模块在试图访问一块已经被释放的内存,然而这块内存是如何被操作的则无从查起,更糟糕的是,QA在内网根本无法重现这个这个错误,必须连接上外网正式服务器才会出现,而且必须运行很长时间后才会出现问题。
由于版本已经发布,玩家不断地投诉让老板黑着脸,已经发话让所有的开发人员必须解决完问题才能回家,经过一番折腾,终于发现原因,原来是一个程序员在改进“TransferItem”这个模块时(就是通过聊天信息传送物品)犯了一个愚蠢的错误,会把背包里不该删除的物品删除,留下一个野指针在那里,当别的模块访问背包时就会出现异常,由于跟所在场景的聊天信息量相关,所以只有在玩家接收到足够的聊天信息后才会发生异常,错误解决了,庆幸之余,我又在想,毕竟开发人员的能力参差不齐,我们可能无法杜绝这种错误的再次出现,那有没有方法能更快的发现这种错误呢。
其实我曾经设想过,如果把我们的程序能够基于一种“可重现”模型的话,问题就会容易的多。
什么是“可重现”模型呢,简单的说,我们的程序可以看作一个盒子,它接收的输入无非就是玩家的操作(鼠标,键盘),网络消息包,窗口消息等,如果我们能把这些输入都记录下来,是不是意味着我们就能够一模一样的重现任何问题呢?
![](http://122.img.pp.sohu.com/images/blog/2007/10/28/14/26/11680c74b2f.jpg)
然而,事实上并不是这么简单,我们的程序还会调用一些其他系统的函数,比如我们会调用Api获得系统时间,会调用C运行时库获得一个随机数,会调用DirectX接口渲染等,运行环境的不同也会使我们的程序走不同的逻辑代码,最简单的例子,程序运行在一台烂机器上会导致两帧之间时间差变大,而这个时间差会导致我们的程序在运行时行为不一致,甚至走不同的switch/case,这是个难解决的问题,但我们并非需要严格意义上的重现,大部分时候记录输入已经足够能帮助我们找到问题了,比如上面举的例子,当时我就是记录下所有接收到的网络消息,然后让逻辑顺序执行,结果重现了这个问题,才最终定位错误的根源的。
相关文章推荐
- 如何解决"应用程序无法启动,因为应用程序的并行配置不正确"问题
- 如何解决"应用程序无法启动,因为应用程序的并行配置不正确"问题
- 工作问题积累(十一)如何解决"应用程序无法启动,因为应用程序的并行配置不正确"问题
- 如何解决"应用程序无法启动,因为应用程序的并行配置不正确"问题
- 如何解决"应用程序无法启动,因为应用程序的并行配置不正确"问题
- 如何解决"应用程序无法启动,因为应用程序的并行配置不正确"问题
- sql-"无法删除数据库,因为该数据库当前正在使用"问题解决
- 关于note2等(Android4.1版本)以上无法启动支付宝的问题"java.security.spec.InvalidKeySpecException"
- SAP 报废资产时出现 "无法找到区域 01 的账户 '资产销售收入的结算科目' " 的解决(二) 解决问题
- 在MacBook 13“机器上无法安装"Boot Camp x64"驱动程序问题的处理
- ls -l |grep "^-"|wc -l 程序问题的定位—strace -p pid(跟踪系统调用)gdb -p pid(调试)lsof -p pid(查看当前进程打开的文件描述符) ps -e
- "... 无法下载Silverlight应用程序。请查看Web服务器设置." 问题的解决方法
- 解决Linux下Qt编译出现"cannot find -lGL"以及无法安装libgl1-mesa-dev的问题
- NET中"无法显示 XML 页。 使用 XSL 样式表无法查看 XML 输入。"问题的解决
- 如何解决adb命令报错 "ADB server didn't ACK"问题
- Missing Dependency: xen-libs",如何解决这个问题?
- chrome浏览器中解决embed标签 loop="true" 背景音乐无法循环的问题。
- "ASP.NET Development Server无法开始侦听端口:XXXX"问题的解决方法
- vs2008 运行时提示"无法打开程序"http://localhost:xxxx/""问题
- MySQL无法登录问题-"ERROR 1045 (28000): Access denied for user 'root'@'localhost'"-之解决方法-密码重置