难以复制的错误是最难解决的问题.您需要确保找到问题的根源,即使问题本身无法成功复制.
最常见的间歇性错误是由竞争条件引起的 - 通过消除竞争,或确保一方总是赢得你已经消除了问题的根源,即使你无法通过测试结果成功确认它.你唯一可以测试的是原因确实需要重复.
有时修复被视为根的东西确实解决了问题,但却没有解决问题 - 没有避免它.避免间歇性错误的最佳方法是对系统设计和体系结构进行谨慎和有条理的处理.
难以复制的错误是最难解决的问题.您需要确保找到问题的根源,即使问题本身无法成功复制.
最常见的间歇性错误是由竞争条件引起的 - 通过消除竞争,或确保一方总是赢得你已经消除了问题的根源,即使你无法通过测试结果成功确认它.你唯一可以测试的是原因确实需要重复.
有时修复被视为根的东西确实解决了问题,但却没有解决问题 - 没有避免它.避免间歇性错误的最佳方法是对系统设计和体系结构进行谨慎和有条理的处理.
如果不确定根本原因并提出可靠的方法来重现错误,您将永远无法验证修复程序.
为了找出根本原因:如果您的平台允许它,请将一些事后调试挂钩到问题中.
例如,在Windows上,让代码在遇到此问题时创建一个minidump文件(Unix上的核心转储).然后,您可以让客户(或Windows上的WinQual)向您发送此文件.这应该为您提供有关代码在生产系统上出错的更多信息.
但如果没有这个,你仍然需要提出一种可靠的方法来重现这个bug.否则你永远无法验证它是否已修复.
即使有了所有这些信息,您最终也可能会修复一个看起来像客户看到的错误但却不是错误的错误.
使用更广泛(可能是可选的)日志记录和数据保存来构建构建,允许精确再现用户在崩溃发生之前所采取的变量UI步骤.
如果该数据不能可靠地让您重现问题,那么您已经缩小了类的bug.是时候查看随机行为的来源了,例如系统配置的变化,指针比较,未初始化的数据等.
有时你"知道"(或者更确切地说)你可以在没有大量测试或单元测试脚手架的情况下修复问题,因为你真正理解了这个问题.但是,如果你不这样做,它往往归结为"我们运行了100次并且错误不再发生,所以我们会考虑将其修复到下次报告时.".
我使用我所谓的"重型防御性编程":在所有看起来与问题相关联的模块中添加断言.我的意思是,添加大量断言,断言证据,在所有成员中断言对象状态,断言"环境"状态等.
断言可帮助您识别与问题无关的代码.
大多数时候,我只是通过编写断言来找到问题的根源,因为它会强制您重新读取所有代码并在应用程序的内容下进行理解.