对于两个错误相互抵消,结果该软件可以按预期工作的情况,有什么名字吗?例如,假设软件A计算了一个值,并且错误地从某处的输入中减去了值X,并且又错误地将完全相同的值(X)加到了值上。因此,我们有两个独立的错误,但是神奇的是,它们消除了它们的副作用,最终计算结果看起来是正确的。

我问这个问题是因为我发现这种类型的错误是最令人困惑和最难发现的错误之一。当我在做其他事情时,我发生了几次,不小心发现了错误/错误/错误。首先,您挠头问自己,到目前为止,它是如何工作的?花费了一段时间,直到您意识到另一个错误已消除了这个错误。
我想知道是否存在此类错误的类别,并且已经对其进行了系统地研究。我想了解更多有关它们以及如何避免/发现它们的信息。

评论

那不是一个bug吗?这可能是次佳的实现,但是如果结果正确,则软件可以按要求运行。

我猜您可以称其为“缺陷掩蔽”,尽管它通常说一个错误被另一个缺陷掩盖了,因为第一个错误不允许您执行包含另一个错误的代码。但是我现在无法提出/记住任何更好的东西。 @jonrsharpe:也许这只是通过算法的一条途径。另一次可能会忽略两者之一(加法或减法),最后给您留下错误的值。

您希望通过询问实现什么?将这种情况作为“相互抵消的多个错误”传达给某人是否存在问题?

有一个灰色区域,第二个错误可能是一种解决方法。有时规格如此不清楚,例如您可能会认为所收到的数据符合规范,尽管并非如此,因此您可以补偿接收端的发送端错误。尽管这两个组件都不能与合规合作伙伴一起使用...

即使第二个错误不是解决方法,@ Peter-ReinstateMonica也正确,将两个模块分开并将它们与另一个模块匹配很可能会发现该错误。正如其他人所提到的,单元测试将有助于防止此问题。

#1 楼

我称它们为掩盖错误。错误1(错误的减法)被错误2(错误的加法)掩盖。

理想情况下,它们会被单元测试捕获-因为单元测试应该报告每个模块是否返回正确的值,并且两个单元的行为均不正确。

由于这不是一个理想的世界,因此,下一个最好的事情就是逐步使用您可以使用的工具。例如,当我处理一项新功能时,通常会先输入基本数据,然后检查输入的数据是否正确保存到数据库中。然后,我开始探索边界和验证方案。在逐步完成并以最小的步骤尽可能多地覆盖应用程序之前,我不会尝试运行完整的端到端方案。

被掩盖的错误并不罕见。它们并不常见,但是它们经常发生,以至于大多数测试人员都遇到了很多测试人员。被掩盖错误抵消(而不是隐藏)的掩盖错误很少见,但仍然会发生。我(不是很喜欢)记得我曾经遇到的一组错误,其中每个更具体的实例都被我首先发现的通用实例掩盖了。我认为最终发现并修复了4个独立的错误,每个错误都比以前的掩盖错误更具体。

评论


相互抵消的掩盖错误在嵌入式和实时系统中可能很常见,例如,由于两个实时中断处理程序的错误指定延迟而隐藏的竞争条件,但可能会在异常情况下浮出水面,例如外部设备发生故障或有人更改时间。您是否对基于环境条件(可能是服务器环境,如网络负载或嵌入式设备与固件交互的物理环境)掩盖的错误有任何见解?

–疯狂
6月2日17:45



对我来说,“掩盖的错误”是指一个错误阻止另一个错误被击中。例如,您有一些代码可以让任何已登录的用户执行管理操作,但是又被另一个阻止用户登录的错误所掩盖。

–马克
6月2日21:25

被掩盖的bug经常出现-相互抵消的bug很少见。生活就是这样,一个小错误掩盖一个关键的,高优先级的错误并不罕见...提防外观修复。

– ptyx
6月2日22:33



无论它叫什么,它肯定是缺乏单元测试的一种表现。

–corsiKa♦
6月3日6:15

我也不认为“掩盖”在这里是正确的术语。不过,这可能取决于具体情况。通常,我同意掩盖意味着通过避免它来隐藏:一个错误隐藏了另一个错误,但是不能同时被它掩盖的错误掩盖。

–卡洛·伍德(Carlo Wood)
6月3日17:06

#2 楼

审计师或会计师会将其描述为“补偿错误”的发生-这在这两个领域中可能更为常见。我认为该术语描述了情况,并且很好地暗含了故障排除和解决方面的挑战。

#3 楼

我一直说这样的代码是“巧合”。

如果您说代码已损坏或有错误,人们会往后推,因为它似乎对偶然的观察者有效。 “巧合”确认该代码确实提供了预期的结果,但是出于错误的原因。人们通常都理解,“巧合”并不是可以安全地依靠的东西,他们倾向于更有可能投入资源来解决问题(至少以我的经验)。很多时候,这些错误是由于在较高级别上测试事物的结果。如果将测试分解为更窄,更集中的测试,以隔离特定的代码单元,则两个相互抵消的bug更有可能最终出现在单独的单元/模块中,因此更加可见。

但是,这并不能抓住所有人。如果这些错误之间的距离足够近(例如您的情况,它们都是单个计算的实现的一部分),那么单独进行测试可能永远无法单独捕获它们。那就是诸如代码审查之类的事情发挥作用的地方。一双新鲜的眼睛通常很擅长发现不适当的东西。对于您的特定示例,静态分析器可能能够将-X+X标记为自毁,并且可以进行优化。

评论


为“巧合作品” +1

– Neil_UK
6月4日4:41

更令人讨厌的是不完全消除错误。我在一个单位上工作,该单位在一个地方有符号错误,而另一个地方固定了错误。它大约在98%的时间内都能正常工作,但是在某些情况下会产生较大的错误,由于部分依赖于传感器输入(每个实验的读数略有不同),它们当然很难复制。 (在现场,我们什至没有意识到有问题。)

–克里斯托波尔多历时城市
6月4日19:52

我称其为“错误”,但我将尝试将其更改为“巧合”。我喜欢您提到的接待方面的差异。

–奥利弗·迈耶(Oliver Meyer)
6月14日6:18

#4 楼

我简单地称它们为相互抵消的错误,并且我怀疑是否有找到或避免它们的特殊方法,以及是否对此进行了任何特殊的研究(我尝试过Google Scholar,但没有发现)。
可能唯一重要的地方是建立产品的统计模型,它们通常假定为单点故障。但是我再次怀疑它是否重要,因为这种错误通常很少见。

#5 楼

我称之为“偶数个错误”。我相信这个词可以归因于我的微积分教授,他曾经在板上犯过“偶数个错误”。错误”可能包括:


建议驾驶员在您表示正确时向左转,但由于方向混淆而使她错误地向右转。
未注意到该消息该公司要带他们的配偶,所以您没有准备足够的食物,然后有人取消了。

我认为这种情况在我的生活中经常发生!

图片: https://www.dreamstime.com

#6 楼

在量子化学中,一个相关的现象称为

“取消错误”

#7 楼

如果您正在处理上述案例@jonsharpe,则可以使用隔离的组件创建示例。

如果它们不解耦,则可能存在隐藏这些错误的可测试性问题。

评论


实际上,我的问题不是解释问题,但我很好奇是否有任何有关此类错误的研究/工作。您提到了去耦/可测试性。是否有任何度量标准可以帮助我们避免此类错误?我猜这种类型的错误的范围与您所拥有的最细粒度的测试一样大。任何解决此类问题的资源/研究。

–CoyBit
6月1日21:29

TDD在设计中解决了这个问题。诸如JDepend之类的工具会收集诸如传入耦合,传出耦合以及与主序列的距离之类的度量。此处提供更多信息:dzone.com/articles/jdepend-design-metrics-ci

–JoãoFarias
6月2日19:30

#8 楼

仅从理论上讲,两个彼此完全抵消的错误是可能的。在任何实际的计算机上,都不可能实现这种完美的抵消。

考虑函数f(x)的非常简单的示例,该函数将整数作为输入并将其加倍。该函数的域为[-INT_MAX / 2,INT_MAX / 2]。 )是两个错误:第一个错误无缘无故地将1000加到结果,然后第二个错误无缘无故地从结果中减去1000。

您可能会说这两个错误相互抵消了输出,因此函数f(x)和函数g(x)相同。但是它们不是相同的功能。有细微的差别。这两个补偿误差改变了函数g(x)的域。添加1000后,它将不再处理域的上限INT_MAX / 2,而不会出现数值溢出错误。该函数的域实际上是[-INT_MAX / 2,INT_MAX / 2-500]。

所以两个函数并不完全相同。

我不知道认为您可以举两个函数的示例,一个函数具有一对补偿误差,另一个函数不具有一对补偿误差,这在各个方面都完全相同。

一对补偿性错误可能很细微,但可以检测到。



对于那些说:“很好。那又怎样?”
考虑:小心点,对函数g(x)的详尽分析将显示其域为[-INT_MAX / 2,INT_MAX / 2-500],这不是我们期望的整数倍函数。因此,尽管存在一对(据说)相互抵消的错误,但它仍然是“越野车”。

评论


“我不认为您可以举一个例子”:我想从星期日= 0开始对一周的每一天进行编号。糟糕!我也意外地将星期六定义为0!哎呀!但是因为我只使用它来计算是否是工作日(天!=周六,天!=周日),所以它永远不会被注意到。修复其中一个错误,代码将中断。

–奇怪的思考
6月3日4:23

@Oddthinking错误的示例:完全没有错误。天数的内部表示只是一种不同而又不同寻常的(但在函数的内部范围内完全有效)。它根本不会使功能失效。现在,如果您更改一个,则会引入一个新的错误。

–Tonny
6月3日14:08

@Tonny:我们似乎对“ bug”的定义感到困惑,而不是解决任何实质性问题。如果另一个开发人员注意到其中一个名称中的错误并提交了错误报告,是否会引起人们的注意?

–奇怪的思考
6月3日14:29

我仍然说“那很好。那又怎样呢?”,因为提出一个非常古怪的理论框架挑战对OP没有帮助。出于实际目的,可能会发生这种情况(根据最严格的定义搁置它们是否不可能),并且比您建议的详尽分析(例如,通过对各个功能进行单元测试)可以更有效地对其进行处理。无论如何,您认为不可能的说法是错误的。考虑例如没有上限的大数据字段。

– JBentley
6月4日9:33

@UnLogicGuys通过这种古怪的逻辑,您也可以很好地争论说没有bug。只有完全按照书面方式工作的软件和完全按组合方式工作的硬件。那不是重点。

–纠缠循环
6月5日,3:13



#9 楼

在大多数情况下,我遇到过这种情况,并不是功能Y的错误被取消,而是在功能X中的错误-它是功能X的错误,由功能Y的不正确补丁所补偿,即有人注意到Y的输出是错误的,因此解决了症状而不是意识到问题出在X中。

以下情况之一将成为问题:


有人发现并修复一个但没有另一个
结果证明,“修复”是部分的,不能涵盖所有问题。
代码重用-有人重用X并“知道”就可以了由于所有先前使用的原因,
由于太多的原因,最终会导致系统运行缓慢
移植到另一个系统/语言/平台
您终于可以进行单元测试了
/>审计员或实习生正看着你的肩膀,想知道为什么如此神奇/复杂。


#10 楼

否:因为这会减少而不是增加问题描述的清晰度。

如果短语或单词不明显,您需要询问其他人,您应该只是“称锹为锹”,而不是“地球和地面清除工具”

#11 楼

我认为这种特殊情况的标题为“错误奇偶校验”。当然,暗示只需要另一个错误来修复现有错误的暗示就有些嘲讽。

#12 楼

运气好吗?

阅读有关情况会引发各种警报/问题,涉及正在使用的测试套件和/或开发人员“修复”错误的方式。看来,许多公司似乎都有一些不称职的编码人员,他们似乎已经习惯了不了解它们的浑水,以至于当发现一个错误时,他们也不在乎真正地解决错误:而不是探究底层。经过全面的分析和可靠的修复,他们采用了更短的路线来提出“骇客”或““头”,虽然这些“骇客”或“”头”似乎(但似乎)起作用;又名,测试人员停止抱怨。 (注意:只有当结果代码为1.实际上正确,2.没有人理解时,您才可以说“黑魔法”或“伏都教编码”(挥舞着一只死鸡),但这显然不是我们在说的大约在这里)。

这里的图片是尝试“随机”的事情,直到测试者不再给出错误为止。这听起来很愚蠢,但是确实很不幸。
(注意:结果是它们每次都规定了截止日期,但创建了像纸牌屋一样的源代码树。无法维护,因为没有任何意义或意义不言而喻,因为任何更改都揭示了大约十二个错误,这些错误在更改之前主要是相互抵消的(对于两个错误,两个容易发现的错误(或者,一个错误和一个“修复”))变成了一个难以发现且难以理解的错误:如此之难,以至于问答和测试套件都不会碰到它,它无法被复制,并且只会在生产环境中的罕见情况下发生。好的编码员(如果说的公司只有一个编码员,则要求编码器)进行调查:/。 ,最后问题将描述为:“ xyz中存在(模糊的东西)错误,该错误在提交ef576c2中已部分修复,但实际上并没有打扮真正的问题”。

同时浪费了很多时间,但是用这个好的编码器来形容它不是:“像往常一样,约翰逊操蛋。那个家伙什么时候才能被解雇?”

革命性的东西似乎可以使自己保持活力:制定截止日期并为产品提供廉价的编码器(无论如何在其他地方都不会提供高薪),然后最终生产出需要不断“维护”的产品,aka在客户已经变得依赖或投入过多资金后仍能继续赚钱,这似乎比同一个应用程序要好得多,该应用程序的成本是后者的四倍,交付时间是后者的两倍(但绝不会失败)。 br />
因此,请阅读您的描述:“运气”(开玩笑)是同一位编码员,否则我将其称为“某人的愚蠢”。

评论


我不喜欢你苛刻的话。但是您声明的核心是正确的:尽管代码按预期运行,但它仍然是一个bug。那些声称没有错误的人忽略了代码的可维护性。人们这样做的原因可能多种多样:代码所有者的概念可能使我无法更改您的代码。太少的测试或规范无法从错误的行为中分辨出正确的行为。成为在代码复杂性上蓬勃发展的英雄程序员。错误的目标:让它发挥作用!简单的愚蠢很少是原因。

–奥利弗·迈耶(Oliver Meyer)
6月14日6:31



#13 楼

在热力学领域,这被认为是“熵态”。现在看起来似乎稳定且平衡,但是最终,所有这些都将崩溃!
听起来,它们实际上不是错误,可能是针对不同情况的。
在微积分中您所拥有的是两个表达式,它们的计算结果相同,具有三个值:
x = yz,y = x + z

#14 楼

我将它们称为“零和错误集”或ZeSBugS,然后将其发音为“ zes错误”。


这些ze漏洞已经2年没有被注意到了。


免责声明:我实际上从未使用过该表达式! :)

#15 楼

如果碰巧是一次合并,则可能会被称为合并。 (但是“补偿”似乎通常是最好的词。)这是一个真实的例子-尽管我承认我正在弥补-但您决定是否可能发生。

有人阅读了GPIO规范,却没有注意到信号被认定为低电平有效。他们编写伪代码以使用他们期望对寄存器进行“或”运算的函数来断言它,但当时还没有完成它。后来,有人编写了按位“或”的代码并检查了操作。他们注意到信号的极性是错误的。为了证明这是问题所在,他们将代码插入AND的逆位。他们测试了代码,使其完美运行,因为当时没有人在调用OR函数。他们去吃午饭。当他们回来时,他们被另一个项目分散了注意力。该项目会交给其他人,这些人首先会编写一个有效的测试。

#16 楼

在粒子物理学和地球物理学的世界中,它们可能被称为“歼灭者”。例如,当尝试对观察到的磁场建模时,信号相互抵消的任何一对磁敏感体都称为an灭器。简约模型的原理(occam的剃刀:使事情保持尽可能简单)意味着应该消除这些an灭者。

我想这个比喻很适合您的情况。

#17 楼

在测试活动中,如果软件返回了预期结果,则没有错误。因此,在功能级别上,这个特定的测试用例将是“ OK”。

通过进行单元测试可以发现错误,这意味着一次测试一个功能。这样可以帮助您识别2个单元错误并进行修复。

#18 楼

“这不只是代码有效吗?”
不,因为:


代码是新鲜蔬菜:它过时,需要刷新。代码只有在可维护的情况下才有价值。神秘的bug使其难以维护。
如果第一个和第二个bug之间发生异常怎么办?出现异常后,第一个错误是活动的!