我们可以保证程序永远不会出错吗?


10

我们在这里有一个系统。最近,系统生成的报告中的数字之一计算错误。根据我们的经验,多年来,我们从未在该系统中遇到任何问题/错误。

由于该系统的编写者已经离开,因此我们几乎无法跟踪程序。但是我们已经验证了输入数据,设置及其正确性。

现在我的问题是,计算机程序会在没有任何逻辑原因的情况下突然出错吗?如果我猛击服务器计算机,计算机正在计算的数字之一会变成另一个数字并使计算错误吗?

我同意我的想法很疯狂,但是我只想知道,我们怎么知道问题不是由程序和输入引起的,而是其他一些因素引起的?

PS这个疯狂的系统没有日志。


8
我PC中的RAM模块之一恰好有一个缺陷位,因此,不幸的是,一个程序无法使用该位可能会导致错误的结果。在您的机器上运行memtest86可能是排除此类问题的简单方法。
user281377 2011年

16
是的,通过删除它
Steven A. Lowe

6
某些硬件实际上存在错误。当今的芯片制造商很少,这证明了这一点。我会首先怀疑该软件。

程序总是有逻辑上的原因要出错。大满贯是合乎逻辑的原因。
mouviciel 2011年

2
您可能拥有统计炸弹,恶意编译器,坏ram,磁盘或可以写入ram或修改OS的病毒,OS错误,操作系统错误,某处库中的错误或著名的合并排序错误,还是...
工作

Answers:


8

我会说不!

理论上答案是否定的,我们只能测试:

  • 一些有限的环境。
  • 一些有限的时间表。
  • 一些有限的测试用例。

这大大少于程序在其生命周期中可能遇到的环境,时间和情况的总数。同样,我们对未来一无所知,您是否应该编程以应对10,000%的通货膨胀,您的程序是否应该应对超级骗子的新型31位架构?

该理论得到了我个人经历的支持:

  • 程序移至其他区域时中断。当月份为“ MAI”时检查“ MAY”。
  • 程序在新版本的编译器上未通过测试,先前版本中的错误与程序中的错误一起产生了正确的结果。
  • 在新版本的OS上中断程序。当Solaris增加默认目录条目数时,由ftok()返回的SMALLINT对于该目录中的第一个文件始终返回零。
  • 程序之所以中断,是因为这是他们第一次遇到特定的输入组合,既有效又出乎意料,并且永远都不会经过测试-存款利率为负,要装运的零重量商品,价值如此之低的商品,无法计算增值税,等等。

我说是,有一项规定-如果您有多线程。曾经听说过“种族状况”。
mattnz

6

从理论上讲,如果您从相同的状态开始,则结果将相同。实际上,在“服务器大小”的设备中确保相同的初始状态几乎是不可能的。

取未初始化的变量。看下面的代码:

  short i;

  if(i==-1)
  {
        //do something special
  }
  else
  {
        i=0;
        //do something else
  }

一旦进行65536次运行,这将产生意外的结果。并且除非您确保每次运行前内存都处于相同状态,否则,i否则它将是完全随机的。

有数百种类似的错误发生方式,这些错误会在人们忘记覆盖的初始状态的不可预测元素或很少发生的边界情况之后弹出-多线程环境中的竞争状况,越界数组访问,损坏的文件系统上的磁盘IO以及以此类推。

如果您可以证明程序没有错误,那么只有宇宙射线可以打破它。但是,比两个嵌套循环更复杂的事物的正确性的数学证明远远超出了最大系统的范围(并且花费不菲),对于所有其他情况,您只能希望。


6

现在我的问题是,计算机程序会在没有任何逻辑原因的情况下突然出错吗?

如果您完全具有相同的计算环境,那么给一个程序输入X总是会产生相同的结果R。实际上,很少有一个程序单独执行。今天最简单的应用程序运行在操作系统中,并与可能同时“加载”在内存中的其他程序共享内存。这些程序可能以使给定程序发生故障的方式更改内存。例如,这是“指针”类型变量的一个著名问题。通常,此类错误会导致系统异常行为,而不会导致错误的计算结果。

对于您的情况,我认为问题可能是(通常不是)我上面描述的问题。问题可能是:

  • 程序使用了错误的数据类型来计算结果,该错误仅在使用特殊值时才会显现出来。
  • 程序在计算中遇到了错误(由于逻辑条件),但没有处理该错误,仍然产生了结果。(例如,将浮点数和整数算术混合)
  • 业务规则或逻辑条件未正确编码,输入的数据表示此条件,但使用了错误的计算。(例如,在先检查帐户中的金额之前,先从帐户金额中减去金额)。
  • 使用仅适用于特定范围数字但数据包含不同范围的公式。(例如,根据一系列值计算利率)

由于上述以及许多其他原因,软件人们花费大量资源来尝试创建正确的软件,但是,软件错误仍然会发生,但是这些错误是“逻辑的”并且是有原因的,只是原因不明显一些没有好的研究。因此,通常来说,经过测试的软件是可预测的,不会产生随机结果。由于某些程序的复杂性和其他因素,即使经过测试的程序也可能出错,但是当发生这种情况时,错误是出于逻辑原因。

如果我猛击服务器计算机,计算机正在计算的数字之一会变成另一个数字并使计算错误吗?

答案通常是否定的,从这个意义上说,软件并不脆弱。

您可以做的是隔离发生错误的情况,找到导致错误的这些数据集之间的相似性,并找出这些错误集与产生正确结果的其他错误集之间的差异。您可能能够识别出导致问题的一组特定值。例如,您可能会发现,变量每次具有负值时,结果都是错误的。

有关内存损坏错误的更新信息:请参阅内存损坏


我本人正在考虑将复合舍入错误视为此类问题的根源。它们可能不会出现很长时间,直到完全正确(或错误)的输入组合导致它们全部组合最终导致与应有的结果背道而驰。
jwenting 2011年

3
现代操作系统不允许程序修改(甚至读取)属于其他程序的内存。
彼得Török

是的,现代操作系统不允许这种性质的任何东西。
2011年

“如果您完全具有相同的计算环境,那么给程序输入X总是会产生相同的结果R”我不确定这是否成立。如果由于某些较早的损坏,内存组件中的一个SR锁存器得到两个1怎么办?en.wikipedia.org/wiki/...
山药Marcovic

@DeadMG和PéterTörök感谢您的反馈,我已经编辑了邮件,并在页面上添加了描述该问题仍然可能发生的参考(我知道如文中所述,这极不可能)。
2011年

5

您能保证程序没有错误并且永远不会出错吗?不,不幸的是没有。

您能否证明程序中的错误数量足够少,以至于发现和修复它们的代价远远超过了从该操作中获得的收益?在我看来,您已经拥有了。

用旧的统计量来解释,所有程序都是错误的,但是有些程序很有用。


1
为“所有程序都错了,但某些程序有用了” +1
CVn

我认为这个答案实际上并不重要。似乎他在问一个正确的程序有时是否由于某些环境缺陷而意外运行。
Yam Marcovic

我的全部观点是,没有程序是“正确的”。一切总是在进行中,只有在错误之前永远是对的。毕竟,计算机科学是一门科学。我确实知道您在说什么,这可能是他的问题重点所在。但是,我认为这使我的回答更加相关,而不是那么无关紧要。
约翰N

@Hallainzil:我相信我已经成功写了正确的“ Hello,World!”。程序之类的。我什至编写了正确的有用程序(尽管不是很大的程序)。
David Thornley

2

我倾向于说没有,你不能证明一个程序将永远不会出错,或提供不正确的结果,即使你可以假设完美的输入。

Raku提到了正确性的正式证明。这是要考虑的一件事,但是除非我完全误解,否则仍然必须假设一个完美的执行环境。因此,通过一些时间和精力,您也许可以证明该程序是正确的,但不一定证明即使给出了完美的输入,它也始终会产生正确的结果。执行环境很重要。我也要谨慎地假设输入总是完美的。

这就是为什么在某些高可用性情况下,将使用多个完全独立的实现和执行环境,并对结果进行比较以确保它们彼此之间在可接受的误差范围内的原因。在某些情况下,该余量很可能为零。甚至早在1960年代,它就已经被认为足够重要,足以在航天器中包括单独的计算硬件集。即使出现错误的静电放电,宇宙射线或同时影响两台计算机的任何事物,以相同方式(特别是如果它们仍在工作并产生有效外观的结果)受到影响的几率也很小。同一错误爬到两个完全独立的实现中的几率也很小。等等。


1

我认为,大多数(标准)计算都是确定性的。

如果可能,将其设置为使用相同的输入数据进行1000次或10000次等批次的迭代,并验证结果是否相同。

确保计算中使用的当前值会在任何地方导致上溢或下溢(如果是较旧的系统,那么可能不打算长时间使用它)。

Y2K11有人吗?


进行N次迭代并验证结果并不能证明正确性。充其量,它证明了样本集内没有错误,甚至假设您的测试用例(及其实现以及执行)都是绝对正确的。尽管测试非常有用,但不能解决OP的问题。
CVn

@Michael也许我应该澄清一下,我不建议尝试使用这种方法来“证明”任何东西,但是如果它进行了无数次迭代而又没有再次显示该错误,那我想就是黑子,而不是整数溢出。恕我直言,它仍然为您提供更多的见解。
jonsca 2011年

1

除非您可以控制机器中的每个位以及流经电路的每个电脉冲,否则您都无法绝对确定程序不会出问题。内存模块出现故障,CPU可能过热并导致错误,硬盘驱动器可能使数据混乱,电源设备可能将噪声引入系统。硬件越昂贵,硬件越冗余,发生这些事情的可能性就越小,但是在某些时候硬件可能会发生故障。

然后,您便拥有了操作系统,并且可以用可以想象的最神秘的方式来修复这些漏洞。编译器可能还存在一些难以理解的错误,只是在等待您将原始代码巧妙地转换为难以追踪的错误。这是一个丛林,您可怜的软件很容易受到所有这些攻击。小心!

根据我的经验,每当计算中出现错误时,我们通常不必花那么多的时间来找到罪魁祸首。一般来说,在企业界见过的几乎所有错误都可以通过正确的调试工具和一些润滑脂轻松找到。

换句话说,尽管硬件和操作系统可能并不完美,但您可能永远不必担心该细节级别。只要找到知道该语言并且熟悉调试器的人,然后再进行深入研究即可。

“在其他条件相同的情况下,简单的解释通常比更复杂的解释更好。” -Occam的剃刀概述。


0

是的,碰到系统可能会使零件弯曲和/或移动足以引起暂时性的开路(或短路,尽管可能性较小)。


0

我拥有的第一台计算机是带有256字节内存的Altair 8080。输入来自控制台开关,输出来自几个闪烁的指示灯。如果您不允许宇宙射线和硬件故障,我相信我可以证明我运行的某些程序始终会产生相同的结果。

从那以后,没有。


0

测试表明存在错误,而不是没有错误(Edsger W. Dijkstra)

如果您试图通过测试证明您的程序可以正常工作,那么它将无法正常工作。

但是,理论计算机科学中有一些方法可以开发出所编写软件的形式证明。但是,根据系统的复杂程度,这可能是一个乏味的过程。但是,如果您的系统在一组受限制的命令上运行,则使用此方法可能会成功。


你读过这个问题吗?
温斯顿·埃韦特

我做到了,我是说他不能使用测试来保证程序永远不会出错。这就是他的问题的标题,对吧?
拉库

是的,标题似乎就是这样。身体显然没有。
Winston Ewert 2012年

0

硬件和软件环境处于不断变化的状态。运动部件,电力,温度,灰尘和OS代码更改就是示例。

因此,我认为,即使环境总是在变化,计算机软件程序也不会或永远不会表现出相同的行为。

软件可以按预期运行很长时间,但是最终,对主机OS软件的微小更改将更改,这将影响所讨论的程序,或者硬件将具有价值。

我说的是当今的计算机。


0

现在我的问题是,计算机程序会在没有任何逻辑原因的情况下突然出错吗?如果我猛击服务器计算机,计算机正在计算的数字之一会变成另一个数字并使计算错误吗?

这个问题的答案是不可知的。不可能证明生活在宇宙中的任何事物都是真实的。相反,我们进行假设并证明如果这些假设成立,那么某些复杂的属性也将成立。这是经过正式验证的程序的保证。但是,大多数程序都未经正式验证,而是尝试通过提供测试来建立信心。这些测试为您提供了保证,只要这些测试能够按照设计的目的进行,并且您所做的假设,所使用的程序至少在某些情况下会起作用。


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.