什么是调试的建议真的很难追踪错误?

时间:2009-04-02 21:48:21

标签: multithreading debugging remoting heisenbug

大多数错误相当简单,易于重现且易于调试。当遇到难以或无法在调试器下重现的那些时,你会做什么,例如these

我们的应用程序是一个多线程的应用程序,由于它通过远程处理与多个客户端进行通信,有时会出现可能需要数周才能跟踪的错误,而且有时我们甚至无法确定问题是固定的,因为它的性质不一致,可能只是巧合这个问题暂时没有出现。

我们已经有了一个错误报告系统,所以如果我们很幸运并且bug会抛出一个异常,我们就会得到一个堆栈跟踪,但即使这样也不够,因为从堆栈中看不出某个值是如何转变的out为null(例如)。在工作线程中发生异常时尤其如此(大多数情况都是如此。

然后你有那些甚至不会抛出异常,这只是意外的行为。但它只发生了一小部分次。

这是在.NET中,因此一些内存/指针工作被隐藏起来,但我们有许多第三方组件不是托管代码和相当数量的COM互操作,所以它仍然有点棘手。

显然没有直截了当的答案,因为我没有询问具体的错误,但是解决这些问题的一般概念原则和策略是什么?

5 个答案:

答案 0 :(得分:1)

嗯,我认为其中一些应该是设计考虑因素,有些人可能称之为“企业关注” - 包含一半不错的日志记录/跟踪和检测将极大地帮助调试(尤其是具有可配置的详细程度!)。即使将几个自定义性能计数器投入到应用程序中,有时也可以帮助调试竞争条件..如果你必须走极端。

第二件事更多的是一种方法或思维方式 - 试图排除组件和环境问题(可能一次一个),它将帮助您缩小异常和其他问题的潜在原因。

最后,拥有一个良好的测试环境,您可以尝试重现相同的条件&例如,错误是一个很大的帮助,即使你必须模拟它而不是重新创建一个物理的计算机网络。

答案 1 :(得分:0)

我知道有一位程序员将他的单元测试留在他的生产代码中,并提供运行它们的能力(通过开关)。他记录所有失败,然后可以查看它们。

显然,这似乎没什么争议,但他说这对于获得有关系统如何在“现实世界”中运作的反馈有很大帮助。

答案 2 :(得分:0)

对于大多数错误,您会在事件发生后找到它们,并通过尝试重新创建环境来修复它们。简单的bug =简单的娱乐。

您的问题的关键是能够重新创建环境。对于像这样的复杂环境,我认为你能做到这一点的唯一方法是采取可能失败的每个接口点,并实现该接口的日志记录,即转储到文件和/或数据库。当然你不希望它一直打开,但你必须在开始时编写它。然后设置一个测试环境,然后可以从日志数据驱动,这样你就可以运行并重新运行环境,直到你重新创建bug,然后你就有80%的方法来解决它。

答案 3 :(得分:0)

在你描述的那种类型的应用中,我的经验是它很容易让凝聚力滑落,并融入到蠕变之中;这些问题最常出现在各个部分之间的界限中。

对于我(鉴于我不完全开发的大师技能),我发现我需要开始寻找简化代码的方法(所以我可以一次更多地了解它),提高碎片的凝聚力(所以范围调查可以尽可能地限制),并对螺纹件进行团队代码审查。

为了强调这一点,不要进行任何不简化设计的更改。

考虑到这一点,“重构”中描述了很多模式。

答案 4 :(得分:0)

系统记录可能会有所帮助:

  • 登录界面,以便将其缩小到一个组件。

  • 当难以从界面上发生的情况推断时,记录内部状态变化。

有时,如果发生故障,系统的某种快照可能会有所帮助。在小型嵌入式系统上,这可能是内存转储,在Java中它可能是线程状态,或者您可以根据命令实现转储适当的状态。