gue*_*rda 62 language-agnostic debugging logging
我们的应用程序中有一个错误,每次都不会发生,因此我们不知道它的"逻辑".我今天甚至没有将它复制100次.
免责声明:此错误存在,我已经看到了.它不是pebkac或类似的东西.
重现这种错误的常见提示是什么?
kro*_*old 27
分析一对中的问题并成对读取代码.记下你所知道的问题是真的,并试着断言这种情况必须适用哪些逻辑先决条件.遵循像CSI这样的证据.
大多数人本能地说"添加更多日志",这可能是一个解决方案.但是对于很多问题,这只会让事情变得更糟,因为日志记录可以充分改变时序依赖性,从而使问题或多或少地发生.将频率从1到1000改为1到1,000,000不会让您更接近问题的真正来源.
因此,如果您的逻辑推理无法解决问题,那么它可能会为您提供一些您可以通过代码中的日志记录或断言进行调查的细节.
Yis*_*hai 21
这个问题没有一般的好答案,但这是我发现的:
这种事情需要人才.并非所有开发人员都最适合它,即使他们是其他领域的超级明星.所以要了解你的团队,他们有天赋,并希望你能给他们足够的糖果让他们兴奋地帮助你,即使它不是他们的领域.
向后工作,并将其视为科学调查.从错误开始,你看到的是错误的.开发关于可能导致它的原因的假设(这是创造性/想象力的部分,不是每个人都有才能的艺术) - 并且它有助于了解代码的工作原理.对于这些假设中的每一个(最好按照您认为最可能的方式排序 - 再次纯粹的肠道感觉),开发一个试图消除它作为原因的测试,并测试假设.任何给定的未能达到预测并不意味着假设是错误的.测试假设,直到确认错误为止(尽管你不太可能首先想要转向另一个假设,但是在你明确失败之前不要打折这个假设).
在此过程中尽可能多地收集数据.广泛的日志记录和其他适用的内容.不要因为缺乏数据而忽视假设,而是要弥补数据的缺乏.通常,正确假设的灵感来自于检查数据.注意到堆栈跟踪中的某些东西,日志中的奇怪问题,数据库中应该存在的缺失等等.
仔细检查每个假设.很多次我看到一个问题没有得到快速修复,因为一些通用方法调用没有进一步调查,所以问题只是假设不适用."哦,那应该很简单." (见第1点).
如果你的假设用完了,那通常是由于对系统知识不足造成的(即使你自己编写了每一行代码也是如此),你需要运行并检查代码并获得对系统的进一步了解一个新的想法.
当然,以上都不能保证任何东西,但这就是我发现的方法可以得到一致的结果.
对于程序员来说,不能仅仅因为你已经开发了一个特定的工作流程和使用该应用程序的习惯而不能重复用户体验的崩溃是很常见的.
在这个1/100的频率下,我要说的第一件事就是处理异常并在任何地方记录任何东西,否则你可能会花费一周时间来寻找这个bug.还要列出项目中可能敏感的关联和功能的优先级列表.例如:1 - 多线程2 - 狂野指针/松散阵列3 - 依赖于输入设备等.这将帮助您按照其他海报的建议将您可以暴力破解的区域再次划分.
由于这是与语言无关的,我将提到几个调试公理.
计算机所做的一切都不是随机的."随机发生"表示尚未发现的模式.调试从隔离模式开始.改变各个元素,并评估是什么改变了bug的行为.
不同的用户,同一台电脑?相同的用户,不同的电脑?该事件是强烈周期性的吗?重启会改变周期吗?
仅供参考 - 我曾经看过一个人经历的错误.我的意思是人,而不是用户帐户.用户A永远不会在他们的系统上看到问题,用户B将坐在该工作站上,以用户A身份登录并立即重现该错误.应用程序应该没有可能的方法来了解椅子中的物理身体之间的差异.然而-
用户以不同的方式使用该应用程序.用户A习惯性地使用热键来调用动作,而用户B使用屏幕控制.用户行为的差异将在稍后的一些操作中级联成可见错误.
应该调查影响bug行为的任何差异,即使它没有任何意义.
您的应用很可能是MTWIDNTBMT(多线程,当它不需要多线程),或者可能只是多线程(礼貌).在多线程应用程序中重现偶发错误的一种好方法是在(C#)周围撒出这样的代码:
Random rnd = new Random();
System.Threading.Thread.Sleep(rnd.Next(2000));
Run Code Online (Sandbox Code Playgroud)
和/或这个:
for (int i = 0; i < 4000000000; i++)
{
// tight loop
}
Run Code Online (Sandbox Code Playgroud)
模拟线程在不同时间完成任务,或者将处理器长时间拉长.
多年来,我继承了许多错误的多线程应用程序,像上面这些示例的代码通常会使得偶发错误更频繁地发生.