如果调试行为与正常执行不同,该怎么办?

时间:2009-07-10 07:48:32

标签: java debugging language-agnostic heisenbug

调试会话有问题。我的程序在调试会话中执行得很好但是如果我开始正常运行,它的行为就完全不同了 问题是,我不能说,为什么它的行为不同。

一个可能的原因是执行时间较慢,因为你总是要按 F6 左右。
我试图插入Thread.sleep(1000);,但我没有得到导致不同行为的指令。

那么:什么是提示,最佳实践来了解它在调试会话中的行为如此不同?

7 个答案:

答案 0 :(得分:11)

两种解决方案:

a)使用穷人的调试器(打印到控制台)或使用日志框架。发生错误后,分析输出。

b)编写试图重现问题的测试用例。即使你不能这样找到它,这也会清理你的代码,有时也会解决问题。

答案 1 :(得分:6)

您可能会观察到只有在没有调试语句减慢执行时才会出现的竞争条件。从审查您的线程模型开始并注意任何可能的锁定可能会有所帮助。

答案 2 :(得分:2)

调试多线程应用程序非常困难。

您可以尝试使用旧的System.out.println技术进行调试,而不是使用调试器......这可能会让您在调试时遇到不同的行为进行调试。

马努

答案 3 :(得分:2)

我试着检查一下我的假设并再次检查它们。

过度记录在某些情况下可能会有所帮助,但并非总是如此。就我而言,它没有那么大的帮助 通过日志记录,您可以看到,您的假设是正确的,哪些是失败的。

我的个人解决方案是Java特定的。自JDK 1.5以来,Java ClassLoader不会完全加载类。在调试会话中,必须完全加载它。因此,一些变量没有很好地初始化,输出与正常运行不同 这个原因很难找到。

答案 4 :(得分:0)

先检查一些简单的东西。崩溃版本是否获得相同的命令行参数?还是特殊的环境变量?还是用户ID?或者你知道的其他一些重要因素。换句话说,您是否真的使用相同的输入运行它。 它一直都会崩溃吗?它会在同一个地方崩溃吗?如果您可以在崩溃后将调试器挂钩,那么它可能会提供一些线索。最近的一些变化是否可能成为罪魁祸首?如果是这样,请尝试删除它,看看会发生什么。

不要过于沉迷于这些尝试。他们只是猜测,如果他们快速得到回报,但最终没有成效,因为“在调试下运行”和“疯狂奔跑”之间存在数百万种可能的差异。

否则,切断差异分析并解决问题。也就是说,直接查看崩溃中出现的问题,而不是迭代可能的原因。

以下是一些可以帮助您“在没有调试器的情况下进行调试”的书籍异常。

Chapter 5, "Debugging" from "The Practice of Programming"

The 9 rules from "The 9 Indispensable Rules for Finding the Most Elusive Software and Hardware Problems

祝你好运!

答案 5 :(得分:0)

注意:不需要多线程相关。

对我来说,它有时会帮助设置不同的断点。

有时评估值会改变它们(例如读取迭代器值) 其次,你的“假”断点可能会抑制并行性和竞争条件。

答案 6 :(得分:0)

我遇到了类似的事情。

我的问题: Set.iteratordebugrun中产生了不同的结果。

当然,我的代码有一个间接依赖于set元素顺序的错误。