有没有调试模式?

时间:2009-11-18 16:03:18

标签: debugging

我知道有许多受欢迎且有用的设计图片。

调试方案有类似的东西吗?也许不是模式,而是分类的方法,可以针对类似情况重复使用。

16 个答案:

答案 0 :(得分:11)

我将添加一个看起来相当明显的调试模式,但还没有说过:

将错误减少到最小的情况,然后将其用作任何建议修复的单元测试。

答案 1 :(得分:8)

以下是一些适合我的方法:

  • 远离问题。与“获得更多睡眠”类似,有时候从问题中解脱出来并专注于完全不同的事情(例如,解决问题)有助于在您恢复问题时提供清晰度。
  • 向我妻子解释问题。嗯,它不一定是我的妻子,而是一个不熟悉问题,系统或任何东西的人。这将迫使你必须在表面上进行假设,解释系统是如何工作的,甚至可以回到代码来验证你在说什么。经过这种交流,我经常取得重大突破。

答案 2 :(得分:7)

我同意其他人关于单元测试作为防止错误的“模式”。另外我想引用Debugging: The 9 Indispensable Rules for Finding Even the Most Elusive Software and Hardware Problems中的以下步骤:

  • 了解系统
  • 让它失败
  • 退出思考,看看
  • 分而治之
  • 一次改变一件事
  • 保持审计跟踪
  • 检查插头
  • 获取全新视图
  • 如果您没有修复它,则无法修复

最后,在更实际的方面,Dimitry Vostokov在他的bookwebsite收集了一些非常好的调试模式。

答案 3 :(得分:5)

当我在黑暗调试中拍摄时,我采用二分搜索方法。我将我的一半代码或一半方法注释掉,沿着这些方向,然后我专注于未注释的一半。如果问题仍然存在,我会评论另一半。等等。

答案 4 :(得分:5)

我的方法是使用科学方法:

  1. 收集有关正在发生的事情的数据,尝试很多不同的输入,看看我得到的输出
  2. 对正在发生的事情提出一个假设
  3. 测试所说的假设,我不对,然后回到第1步并重复。

答案 5 :(得分:5)

如果您有一段曾经工作的代码,现在出现错误和完整版本历史记录,那么通过历史记录进行二进制搜索会非常有用。您在工作提交和非工作提交之间选择一个点,然后编译并测试。如果该提交显示错误,你知道它是从这里或更早开始的,所以你回到这里和已知的良好提交中间并再次测试;否则,你知道错误是在以后开始的,所以你要在这里和已知的错误提交之间中途前进,并在那里进行测试。你继续关注这个过程,直到你发现哪个提交引入了bug,然后你看看发生了什么变化,这个问题很有可能是显而易见的。

git bisect是一个非常出色的工具。但理论上你可以用一堆tarball做同样的事情,如果这就是你所拥有的。

当然,如果错误多次进出树,这将无效。如果您的提交不是非常精细,那么它可能不会非常有用。

答案 6 :(得分:4)

我喜欢认为单元测试是一种调试模式。如果您可以重现该问题,您可以编写单元测试以使其更容易调试。

一旦您进行了用于调试问题的“顶级”单元测试,您总是可以在代码中以较低和较低级别创建更多失败单元测试,以帮助您在添加单元测试时专注于错误这对你的项目来说是长期有用的。

答案 7 :(得分:3)

故障隔离就是其中之一。问题是在所有操作系统上发生的,还是只与一个操作系统有关?

继续二分法确定问题的位置和原因。

答案 8 :(得分:3)

我调试的方式是我解决问题的方式。我使用cartesian方法。

有4 rules

  • 不接受任何真实的,因为原因不能被清楚明确地识别出来;
  • 通过将复杂的想法分解为简单的构成要素来分析它们,这个原因可以直观地理解;
  • 重建,从简单的想法开始,综合工作到复杂的;
  • 要准确,完整地列举问题数据,请在此步骤中使用归纳和演绎方法。

或者说differently

  • 只接受不容置疑的内容。
  • 将每个问题分成易于管理的部分。
  • 从最简单的问题开始,然后提升到更复杂的问题。
  • 经常回顾以立即保留整个论点。

您只需在编程环境中调整这些规则。

如果我不得不恢复,我会说问题/错误是它的简单表达。迭代地做。

答案 9 :(得分:1)

有一些更正式的模式可以消除特定的错误:

  • 消除噪音模式
  • 重新出现的错误模式
  • 特定时间错误模式

但是,我认为您的大多数调试决策和工作流程都将由您使用的环境设计。

答案 10 :(得分:1)

我遇到的只有几个:

  • 当两个相同的系统是 产生不同的结果,验证 (按可能性排序):
    • 所有组件的版本都在 事实上,两者相同 系统,
    • 配置完全相同 两个系统之间,和
    • 有 没有一个系统上的残留数据 另一方面没有出现。
  • gdb和 gcc解析代码比我好。让 软件可以帮助您完成工作 你的。
  • 当数据出现在与您期望的过程不同的过程的一端时,请验证整个过程中的数据以验证其是否符合预期,而不是关注过程中从真实问题下游的功能
  • 如果您没有确认这是导致错误的原因,请不要专注于特定的代码。
  • 多睡一觉。警报调试总是更有效。

我的软件开发网站上有更多内容 - >调试如果你有兴趣。

答案 11 :(得分:1)

这不是一种真正的调试技术,但我认为我们必须提到一个调试前置条件,如果不满足,将会使你的工作变得更加复杂。

在错误可重现之前,您无法真正开始有意义的调试,并逐步完成配方。如果你得到一个糟糕的错误报告,你可能最终必须亲自辨别该食谱,但如果你支持某人,你应该让他们知道你找出这个食谱需要比他们为你做的更长的时间,甚至可能是不可能。一个有用的错误报告必须回答我称之为错误报告公式的三个问题:1)你做了什么? 2)你期望发生什么? 3)反而发生了什么?

当然,有些虫子是Heisenbugs,显然是短暂的。您仍然应该尝试获得类似于“如果我执行以下操作的声明,看起来大约有10%的时间会发生这种不良结果。”

一旦你有了这个配方,下一步就是经常煮沸到最小的测试用例,就像其他人提到的那样。

答案 12 :(得分:0)

其他人(Xynth,Broam,Moshe)已经提到需要获得最小的测试用例,希望可以将其插入到您的单元测试套件中。我同意。一旦你可以让错误发生,开始削减额外的因素,甚至代码(如鲍勃建议的那样),在每一步测试以查看错误是否消失。如果它在cron中,请手动运行。如果它是从GUI运行的,请从命令行或简单的测试套件中尝试。

如果遇到麻烦,相反的方法通常很有用:创建一个微小的,最小的程序,它可以完成错误例程所做的一些事情。测试它,看看你是否有bug。然后,一步一步,尝试编写一个工作程序,执行错误例程应该做的事情。在某些时候,您可能会看到显示的错误,在这种情况下,您现在有了测试用例。或者,您可以一路走向成功的日常生活。在这种情况下,开始逐行将该例程转换为代码的精确副本,并一路测试以查看错误何时出现。

答案 13 :(得分:0)

专门针对OpenGL片段着色器调试,这是非常不透明的。 Dumbing东西是好的和必要的,但检查输出比常规应用程序编程更棘手,所以你需要一些技巧:

  • 如果需要检查精确的值更改,请使用步骤()在r,g,b中渲染不同的部分。 (适用于检测浮点错误,如1.001或-0.001)
  • 学习将rgb解释为规范化的xyz向量。
  • 删除纹理样本,将纹理坐标绘制为颜色。
  • 考虑在屏幕的不同部分呈现不同的变量,并使用自由浮动相机。

答案 14 :(得分:0)

感谢所有想法。他们真的很有帮助。据我所知,在修复bug方面没有像Design Patterns这样的模式列表。也许在某种程度上,每个人都有自己的方式。

我使用的一种方法是,如果过程看起来很复杂,那就坐下来试着看看我是否可以对代码进行一些重新分解。这让我有机会重新思考代码的行为,更好地理解并使其更易于维护。提取方法是我最喜欢的可读逻辑单元。

我最喜欢的一件事是,如果以意想不到的方式更改属性的值,我会在该属性的setter上设置一个断点。我不知道是否可以使用隐式属性减速(bool myProperty {get; set;})来实现它。

也许最好先让BUG目录显示所有类型的错误分类。

感谢, burak ozdogan

答案 15 :(得分:0)

Dmitry Vostokov一直在http://www.dumpanalysis.org/

编制许多调试模式

他在博客http://www.dumpanalysis.org/blog/

中写了很多关于他们的文章

虽然主要处理Windows平台上的调试,但他已开始在Mac OS上发布关于gdb的博客。