最难追踪的错误types?

什么是一些最难处理,最难处理的错误,为什么?

在我们发言的过程中,我都非常好奇和深深地陷入困境。 正如他们所说 – 痛苦喜欢公司。

海森堡 :

一个海森堡不确定性原理(Heisenberg Uncertainty Principle)命名的海森堡(Heisenbug)是一个计算机bug,当试图研究它时,它会消失或者改变它的特征。

种族条件和僵局。 我做了很多multithreading的进程,这是最难处理的事情。

在发布模式下编译但在debugging模式下不会发生的错误。

任何基于时间条件的错误。 当使用线程间通信,外部系统,从networking读取,从文件读取或与任何外部服务器或设备通信时,通常会遇到这些问题。

不是在你的代码本身,而是在你所依赖的供应商模块中的错误。 特别是当供应商没有反应时,你不得不破解工作。 非常沮丧!

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

单词和定义进行得很好,我可以在Management Studio中看到所有的东西。 但是,无论何时我们试图find给定单词的定义,我们的查询都不会返回。 经过坚实的8个小时的debugging之后,我开始认为自己已经失去了编写一个简单的SELECT查询的能力。

也就是说,直到我注意到英文字母与其他英文字母相匹配,并带有任何数量的外来字母。例如, 英语字符将匹配E!n @ gl ## $ ish $&Word 。 (用!@#$%^&*表示外来字母)。

当整理不知道某个字符时,它不能对它们进行sorting。 如果它不能sorting,它不能分辨两个string是否匹配(对我来说是一个惊喜)。 如此令人沮丧,整整一天下来,愚蠢的整理设置。

攻击错误,特别是竞赛条件。 当你不能停止系统(因为错误消失),事情很快就会变得艰难。

我经常遇到的最难的是没有出现在任何日志追踪中的。 你永远不应该默默地吃一个exception! 问题在于进食exception经常会将您的代码移入无效状态,而在另一个线程中则以无关联的方式失败。

也就是说,我遇到的最困难的一个是函数调用中的C程序,其中调用的签名与被调用的签名(一个是长的,另一个是int)不完全匹配。 在编译时或链接时没有错误,并且大多数testing都通过了,但是堆栈被sizeof(int)closures了,所以在堆栈之后的variables会随机地有一个错误的值,但是大多数时候它会正常工作那个坏参数之后的值通常被作为零传入)。

这是一个跟踪的BITCH。

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

  • 错误发生在一台服务器上而不是另一台服务器上,而且你无法访问有问题的服务器来进行debugging。
  • 与线程有关的错误。

对我来说最令人沮丧的是编译器错误,代码是正确的,但是我碰到了一个没有logging的angular落案例或编译器错误的地方。 我首先假设我犯了一个错误,然后花了好几天的时间去find它。

编辑:其他最令人沮丧的是我的testing用例设置了一些错误,所以我的代码是正确的,但testing不是。 那花了好几天才find。

总的来说,我想我遇到的最糟糕的错误是那些不是我的错。

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

  • 由第三方报告,但不能在您自己的testing条件下复制;
  • 错误发生很less和不可预知(例如,因为它是由竞争条件造成的);
  • 错误是在embedded式系统上,你不能附加一个debugging器;
  • 当您尝试获取日志信息时,错误消失;
  • 错误是在第三方代码,如图书馆…
  • …你没有源代码,所以你只能使用反汇编;
  • 而且错误在于多个硬件系统之间的接口(例如,networking协议错误或总线争用错误)。

我本周正在研究所有这些function的错误。 有必要对图书馆进行反向工程,以了解它到底是什么; 然后产生关于哪两个设备在竞赛的假设; 然后制作专门用于激发假设竞争条件的程序版本; 那么一旦确认了其中一个假设,就可以使事件的时间同步,以便图书馆在100%的时间内赢得比赛。

曾经使用过Crystal Reports?

有一个项目build立一个使用贝奥武夫集群的化学工程模拟器。 恰巧网卡不会传输一个特定的字节序列。 如果数据包包含该string,数据包将丢失。 他们通过更换硬件解决了这个问题 – 首先发现硬件要困难得多。

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

这个bug需要几个小时才能出现,而当它出现的时候,通常只有在程序弄得这么糟糕的时候才会注意到它的相当长的一段时间,它开始行为不端。 在代码库中缩小到发生错误的位置非常困难,因为在损坏内存的函数中从未发生由于内存损坏导致的崩溃,并且为了使错误显示出来,花了很长时间。

这个bug在一个很less被调用的代码片段中是一个错误的错误,用来处理一个有问题的数据行(从内存中无效的字符编码)。

最后debugging器被certificate是无用的,因为在调用树中没有发生崩溃事件。 一个顺序良好的fprintf(stderr,…)stream调用代码并将输出转储到一个文件,这最终使我们能够确定问题所在。

我的一个朋友有这个bug。 他不小心把一个函数参数放在方括号中的C程序中,而不是像这样括起来: foo[5]而不是foo(5) 。 编译器非常高兴,因为函数名是一个指针,关于索引指针没有任何不合法之处。

对于我来说最令人沮丧的是algorithm在软件规范中是错误的。

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

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

其中最难的一个实际上是我帮助一个朋友的一个错误。 他在MS Visual Studio 2005中写C,忘记包含time.h. 他进一步调用没有必要参数的时间,通常是NULL。 这隐式宣布的时间,如:int time(); 这会损坏堆栈,并且以完全不可预知的方式。 这是一个很大的代码,我们没有想到在相当一段时间看()调用。

并发错误很难跟踪,因为当你还不知道错误是什么的时候,再生它们可能非常困难。 这就是为什么,每次在日志中看到一个无法解释的堆栈跟踪时,都应该search该exception的原因,直到find它为止。 即使它只发生在一百万的一次,也并不重要。

既然你不能依靠testing来重现错误,你必须使用演绎推理来找出错误。 这又需要深入理解系统的工作原理(例如,Java的内存模型是如何工作的以及什么是并发错误的可能来源)。

下面是几天前我刚才find的Guice 1.0中的一个并发错误的例子。 您可以通过试图找出造成该exception的错误来testing您的错误发现技能。 这个错误不难find – 我在15-30分钟内find了它的原因(答案在这里 )。

 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 ... 

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

缓冲区溢出(以本机代码)

去年,我花了几个月的时间跟踪一个问题,最终成为下游系统的一个漏洞。 来自违规系统的团队一直声称,即使我们按照他们所要求的方式传递数据,它在我们的处理过程中一定是有趣的。 如果领导者能够多一点合作,我们可能会更早地纠正错误。

未初始化的variables。 (或者有现代语言完成了这个?)

追踪难度:

  • 逐个错误
  • 边界条件错误

依赖机器的问题。

我目前正在尝试debugging为什么应用程序在try / catch块(是的,在try / catch内部未处理)中只有在特定的OS /机器版本上才会显示,而在其他版本上没有处理的exception。

相同版本的软件,相同的安装介质,相同的源代码,对某些未处理的exception有效,这些exception应该是其他代码中处理得很好的部分。

GAK。

当对象被caching,并且它们的equals和hashcode实现被实现得如此糟糕,以至于hash码值不是唯一的,equals在不相等的时候返回true。

在各种浏览器操作系统configuration中,例如,在Windows和Mac中,在Firefox和IE中浏览器的外观都很美观,但在Safari中的Mac上,某些化妆品的网页错误会被搞乱。 这些烦人有时是因为他们需要太多的注意细节,并做出修改Safari的可能会打破Firefox或IE中的东西,所以人们必须谨慎行事,意识到造型可能是一系列的黑客修复一页一页的。 我会说这些是我最不讨人喜欢的,有时候因为没有被认为是重要的而没有得到解决。

回想起那些日子,内存泄漏。 谢天谢地,这些天有很多工具可以find它们。

内存问题,特别是在旧系统上。 我们有一些传统的16位C软件,暂时必须保持16位。 64K内存块是非常痛苦的工作,我们不断添加静态或代码逻辑,推动我们超过了64K组限制。

更糟糕的是,内存错误通常不会导致程序崩溃,但会导致某些function偶尔中断(而不总是相同的function)。 debugging是一个非选项 – debugging器没有相同的内存约束,所以程序在debugging模式下总能正常运行……另外,我们不能添加内联的printf语句来testing,因为这会使内存使用率更高。

因此,我们有时可能会花费DAYS试图查找一段代码来重写,或者将静态字符移动到文件中。 幸运的是,这个系统正在慢慢地被移走。

multithreading,内存泄漏,需要大量模拟的任何事情,与第三方软件接口。