最难跟踪的错误类型?

时间:2009-02-20 16:55:10

标签: debugging language-agnostic testing

您需要跟踪和修复哪些最恶劣,最难以处理的错误以及为什么?

在我们发言的过程中,我既是真正的好奇又是膝盖深处。正如他们所说 - 苦难喜欢公司。

35 个答案:

答案 0 :(得分:79)

Heisenbugs

  

heisenbug(以海森堡不确定性原则命名)是一种计算机错误,当试图研究它时,它会消失或改变其特征。

答案 1 :(得分:45)

竞争条件和死锁。我做了很多多线程流程,这是最难处理的事情。

答案 2 :(得分:30)

在发布模式下编译但未在调试模式下编译时发生的错误。

答案 3 :(得分:24)

任何基于时间条件的错误。这些通常在使用线程间通信,外部系统,从网络读取,从文件读取或与任何外部服务器或设备通信时出现。

答案 4 :(得分:22)

本身不在代码中的错误,而是在您依赖的供应商模块中。特别是当供应商没有反应时,你被迫破解解决方案。很沮丧!

答案 5 :(得分:13)

我们正在开发一个数据库来保存另一种语言的单词和定义。事实证明,这种语言最近才被添加到Unicode标准中,并没有进入SQL Server 2005(尽管它是在2005年左右添加的)。在整理时,这会产生非常令人沮丧的效果。

单词和定义很好,我可以在Management Studio中看到所有内容。但每当我们试图找到给定单词的定义时,我们的查询都没有返回任何内容。经过8个小时的调试后,我才开始认为我已经失去了编写简单SELECT查询的能力。

也就是说,直到我注意到英文字母与其他英文字母相匹配,其中包含任意数量的外国字母。例如, EnglishWord 将匹配 E!n @ gl ## $ ish $ &安培;字即可。 (用!@#$%^& *代表外国字母)。

如果排序规则不知道某个字符,则无法对其进行排序。如果它无法对它们进行排序,则无法判断两个字符串是否匹配(对我来说是一个惊喜)。非常令人沮丧,整整一天都在愚蠢的整理设置。

答案 6 :(得分:10)

线程错误,特别是竞争条件。当你无法阻止系统时(因为bug消失了),事情很快变得艰难。

答案 7 :(得分:10)

我经常遇到的最困难的是那些没有出现在任何日志跟踪中的。你永远不应该默默地吃一个例外!问题是,吃异常通常会将代码移动到无效状态,以后它会在另一个线程中以完全不相关的方式失败。

那就是说,我遇到的最困难的一个是函数调用中的C程序,其中调用签名与被调用签名不完全匹配(一个是long,另一个是int)。在编译时或链接时没有错误,并且大多数测试都通过了,但是堆栈由sizeof(int)关闭,因此堆栈上的变量会随机出现错误的值,但大多数情况下它会正常工作(该错误参数后面的值通常被传递为零)。

这是一个跟踪的BITCH。

答案 8 :(得分:9)

由于硬件故障导致内存损坏。

答案 9 :(得分:8)

  • 在一台服务器而不是另一台服务器上发生的错误,并且您无法访问违规服务器进行调试。
  • 与线程有关的错误。

答案 10 :(得分:7)

对我来说最令人沮丧的是编译器错误,其中代码是正确的但是我遇到了一个未记录的极端情况或编译器错误的地方。我开始假设我犯了一个错误,然后花了好几天试图找到它。

编辑:另一个最令人沮丧的是我把测试用例设置稍微错误的时候,所以我的代码是正确的,但测试不是。这花了好几天才找到。

总的来说,我猜我遇到的最糟糕的错误就是不是我的错。

答案 11 :(得分:6)

追踪和修复最难的错误是那些结合所有困难情况的错误:

  • 由第三方报告,但您无法在自己的测试条件下复制;
  • bug很少发生且不可预测(例如因为它是由竞争条件引起的);
  • bug在嵌入式系统上,您无法附加调试器;
  • 当你试图获取日志信息时,bug就会消失;
  • 错误在第三方代码中,例如库...
  • ...您没有源代码,因此您只能使用反汇编;
  • 并且该错误位于多个硬件系统之间的接口处(例如,网络协议错误或总线争用错误)。

本周我正在处理所有这些功能的错误。有必要对图书馆进行逆向工程以找出它的内容;然后产生关于哪两个设备正在比赛的假设;然后制作旨在激发假设竞争条件的程序的特别装备版本;然后,一旦其中一个假设被确认,就可以同步事件的时间,以便图书馆100%的时间赢得比赛。

答案 12 :(得分:5)

并发错误很难跟踪,因为当你还不知道错误是什么时,重现它们会非常困难。这就是为什么每次在日志中看到无法解释的堆栈跟踪时,都应该搜索该异常的原因,直到找到它为止。即使它只发生在一百万次中,也不会使它变得不重要。

由于您不能依赖测试来重现错误,因此必须使用演绎推理来找出错误。这反过来需要深入了解系统的工作原理(例如Java的内存模型如何工作以及可能的并发错误来源)。

以下是我在几天前找到的Guice 1.0中的并发错误示例。您可以通过尝试找出导致该异常的错误来测试您的错误查找技能。这个错误并不难找 - 我在15-30分钟内找到了它的原因(答案是here)。

java.lang.NullPointerException 
    at com.google.inject.InjectorImpl.injectMembers(InjectorImpl.java:673) 
    at com.google.inject.InjectorImpl$8.call(InjectorImpl.java:682) 
    at com.google.inject.InjectorImpl$8.call(InjectorImpl.java:681) 
    at com.google.inject.InjectorImpl.callInContext(InjectorImpl.java:747) 
    at com.google.inject.InjectorImpl.injectMembers(InjectorImpl.java:680) 
    at ...

P.S。有缺陷的硬件可能会导致比并发更糟糕的错误,因为可能需要很长时间才能自信地断定代码中没有错误。幸运的是,硬件错误比软件错误更为罕见。

答案 13 :(得分:5)

我必须找到的最难的错误之一是内存损坏错误,只有在程序运行数小时后才会发生。由于破坏数据所花费的时间很长,我们假设硬件并首先尝试了两台或三台其他计算机。

这个错误需要几个小时才能出现,当它出现的时候通常只会在程序搞砸了之后才会发现相当长的一段时间它开始行为不端。在代码库中缩小到发生错误的位置是非常困难的,因为内存损坏导致的崩溃从未发生在损坏内存的函数中,并且错误显示了很长时间。

该bug在一个很少被调用的代码片段中被证明是一个错误的错误,用于处理有错误的数据行(内存中的字符编码无效)。

最后,调试器被证明是无用的,因为在违规函数的调用树中从未发生过崩溃。 fprintf(stderr,...)的良好排序流在代码中调用并将输出转储到文件中,这最终使我们能够识别出问题所在。

答案 14 :(得分:5)

有一个项目使用beowulf集群构建化学工程模拟器。碰巧网卡不会传输一个特定的字节序列。如果数据包包含该字符串,则数据包将丢失。他们通过更换硬件解决了这个问题 - 首先发现硬件要困难得多。

答案 15 :(得分:4)

我的一个朋友有这个错误。他不小心将函数参数放在方括号中的C程序中,而不是像这样的括号:foo[5]而不是foo(5)。编译器非常高兴,因为函数名是一个指针,并且没有关于索引指针的非法行为。

答案 16 :(得分:4)

最难的一个实际上是我帮助朋友的一个错误。他在MS Visual Studio 2005中编写C,忘了包含time.h.他进一步调用了没有必需参数的时间,通常为NULL。这隐式声明的时间如下:int time();这会以完全不可预测的方式破坏堆栈。这是一个很大的代码,我们没想到看一下时间的time()调用。

答案 17 :(得分:4)

可能不是最难的,但它们非常普遍而且不是微不足道的:

  • 有关可变状态的错误。如果数据结构中有多个可变字段,则很难在数据结构中维护不变量。而且你有操作顺序依赖 - 交换两行,发生了一些不好的事情。我最近发现的一个难以发现的错误是当我发现系统的先前开发人员使用哈希表键的可变数据时 - 在一些罕见的情况下会导致无限循环。
  • 初始化错误的顺序。发现时可以很明显,但编码时则不然。

答案 18 :(得分:4)

对我来说最令人沮丧的是软件规范中的算法错误。

答案 19 :(得分:3)

去年,我花了几个月的时间来跟踪一个问题,最终导致下游系统出现问题。来自违规系统的团队领导一直声称在我们的处理过程中它必须是有趣的,即使我们传递的数据就像他们从我们这里请求的那样。如果领导能够更加合作,我们可能会更快地确定错误。

答案 20 :(得分:3)

未初始化的变量。 (或者用现代语言取消了吗?)

答案 21 :(得分:3)

缓冲区溢出(在本机代码中)

答案 22 :(得分:2)

跟踪难度:

  • off-by-one errors
  • 边界条件错误

答案 23 :(得分:2)

毫无疑问,内存泄漏。特别是当你在ASP.NET中动态创建控件和添加处理程序时。在页面加载。

答案 24 :(得分:2)

对于嵌入式系统:

客户在现场报告的异常行为,但我们无法重现。

之后,由于一系列怪异事件或事件的同时发生的错误。这些至少是可重复的,但显然它们可能需要很长时间 - 而且需要大量的实验 - 才能实现。

答案 25 :(得分:2)

多线程,内存泄漏,任何需要大量模拟的东西,与第三方软件连接。

答案 26 :(得分:2)

内存问题,特别是在旧系统上。我们有一些传统的16位C软件,暂时必须保持16位。 64K内存块是很难用的,我们不断添加静态或代码逻辑,使我们超越64K组限制。

更糟糕的是,内存错误通常不会导致程序崩溃,但会导致某些功能偶尔中断(并不总是相同的功能)。调试是一个非选项 - 调试器没有相同的内存限制,所以程序总是在调试模式下正常运行...而且,我们无法添加内联printf语句进行测试,因为这会使内存使用率更高。

因此,我们有时可能会花费DAYS来查找要重写的单个代码块,或者将静态字符移动到文件的时间。幸运的是,系统正在慢慢脱机。

答案 27 :(得分:2)

回到过去,内存泄漏。值得庆幸的是,现在有很多工具可以找到它们。

答案 28 :(得分:2)

涉及各种浏览器O / S配置中的样式的化妆品网络错误,例如,在Firefox和IE中,Windows和Mac中的页面看起来很好,但在Safari中的Mac上有些东西搞砸了。这些都很烦人,因为它们需要非常注重细节,并且修改Safari可能会破坏Firefox或IE中的某些内容,因此必须谨慎行事,并认识到样式可能是一系列黑客一页一页地修复。我会说这些是我最讨厌的,有时候不会被修复,因为它们不被认为是重要的。

答案 29 :(得分:2)

与机器有关的问题。

我正在尝试调试一个应用程序在try {} catch {}块中有未处理的异常的原因(是的,在try / catch中未处理)只在某些OS /机器构建中出现,而不是在其他

相同版本的软件,相同的安装媒体,相同的源代码,适用于某些 - 未处理的异常,应该是其他代码中处理得非常好的部分。

GAK。

答案 30 :(得分:2)

当对象被缓存并且它们的equals和hashcode实现实现得太差以至于哈希码值不是唯一的,并且当equals不相等时,equals返回true。

答案 31 :(得分:1)

线程泄漏,你经常忘记计算线程数

答案 32 :(得分:0)

这纯粹是虚构的,但是艾伦·厄尔曼的The Bug是一个很难找到的带有悲剧性后果的错误的故事。

答案 33 :(得分:0)

edbdic系统上的字符转换问题,其中处理此问题的系统机制已被禁用 - urgh

答案 34 :(得分:0)

处理用户在与网站连接时打开多个标签的情况。很难避免数据连续性问题。取决于我猜的应用程序,但这是我们花了很多时间解开的东西!