代码正确性证明会成为主流吗?[关闭]


14

除了最琐碎的程序外,所有程序中都充满了错误,因此承诺删除它们的任何事情都非常诱人。目前,正确性证明是非常深奥的代码,主要是由于学习起来很困难,以及证明程序正确所付出的额外努力。您认为代码验证会成功吗?

Answers:


8

从这个意义上讲并不是真的,但是纯函数式编程在这个领域是不错的。如果您使用Haskell,则如果代码编译,则程序很可能是正确的。除了IO之外,一个好的类型系统是一个很好的帮助。

合同编程也可能会有所帮助。请参阅Microsoft代码合同


6
抱歉-我并没有做太多的“现实世界” Haskell,但是我已经做了足够多的教程练习,可以持续一生。仅仅因为它编译并不意味着它可能起作用。与Ada(之所以选择它,是因为它是一种严格的静态类型的命令式语言)相比,我想说Haskell稍微容易一些,但是主要是因为它更简洁(循环复杂度较低)。在处理IO monad时,会有一些烦恼会使Haskell 变得更难以正确处理-与命令式风格足够不同,有些事情它自然无法做到。
Steve314 2011年

关于“自然不能做”,请考虑“ while”循环。是的,您可以自己滚动-但while条件必须在monad之内,因为它需要对循环体的副作用做出反应。这不仅意味着您已获得在while条件内引起副作用的权限,也使使用while循环变得很尴尬。最终结果-即使在IO monad代码中,使用递归通常也更容易-这意味着您必须以特定的方式构造事物。
Steve314 2011年

14

除了最琐碎的程序之外的所有程序

无法通过合理的努力充分证明其正确性。对于任何形式的正确性证明,您至少需要一个正式的规范,并且该规范必须完整且正确。通常,对于大多数实际程序而言,您很容易创建任何东西。例如,尝试为此类讨论站点的用户界面编写类似的规范,您就会明白我的意思。

在这里,我找到了一篇有关该主题的不错的文章:

http://www.encyclopedia.com/doc/1O11-programcorrectnessproof.html


正确-对于任何编程项目,都有一个从问题的非正式描述到正式的描述(通常是今天,以程序的形式)的过渡,并且这种过渡不会消失。
David Thornley

astree.ens.fr在此处查看Astrée的工业应用
zw324

@ZiyaoWei:这样的工具很有用,但它们只会发现一些形式上的错误,而没有更多。如果像这样的单行程序printf("1")正确与否(例如,由于要求是“打印从1到6的均匀分布的随机数”),则无法通过这种静态分析器确定。
布朗

10

形式证明的问题在于,它只会使问题退后一步。

说一个程序正确是等同于说一个程序做了它应该做的事情。您如何定义程序应该做什么?您指定它。以及您如何定义程序在规范未涵盖的极端情况下应采取的措施?好吧,那么您必须使规格更详细。

因此,可以说您的规范终于变得足够详细,可以描述整个程序各个方面的正确行为。现在,您需要一种使证明工具理解它的方法。因此,您必须将规范翻译成证明工具可以理解的某种形式的语言……嘿,等等!


2
另外,“请注意上面代码中的错误;我只证明了它是正确的,没有尝试过。” -唐纳德​​·努斯(Donald Knuth)
布伦丹(Brendan)

8

正式验证已经走了很长一段路,但通常行业/广泛使用的工具落后于最新研究。这是朝着这个方向的一些最新努力:

Spec#http://research.microsoft.com/zh-cn/projects/specsharp/ 这是C#的扩展,它支持代码协定(前后条件和不变式),并且可以使用这些协定进行各种类型的静态分析。 。

对于其他语言,也存在与此类似的项目,例如Java的JML,而Eiffel具有很多内置功能。

更进一步,诸如slamblast之类的项目可用于以最少的程序员注释/干预来验证某些行为属性,但仍无法处理现代语言的全部一般性(不模拟整数溢出/指针算术之类的事物)。

我相信,将来我们会在实践中看到更多这些技术。主要的障碍是没有手动注释就很难推断出程序不变量,并且程序员通常不愿意提供这些注释,因为这样做太繁琐/耗时。


4

除非出现一种无需大量开发人员就能自动证明代码的方法。


考虑一下经济上的争论:对于开发人员来说,用正确性证明“浪费”时间可能比因软件错误而浪费金钱更好。
安德列斯·F

我同意fishtoaster的看法,除非它变得不那么占用大量资源,否则大量的常规商业软件将不会具有支持这种正确性水平的成本/收益。在LOB应用程序中,对于被俘虏的用户而言,有时,关于错误报告的最大的商业收益就是在文档中添加一行“不要这样做”的
Bill

3

一些形式化的方法工具(例如,用于关键嵌入式C软件的Frama-C)可以被视为(分类)提供或至少检查给定软件的(正确性)证明。(Frama-C在某种意义上检查程序是否遵守其正式规范,并尊重程序中明确标注的不变式)。

在某些领域,这种正式的方法是可能的,例如用于民用飞机关键软件的DO-178C。因此,在某些情况下,这样的方法是可行且有用的。

当然,开发较少错误的软件非常昂贵。但是形式化方法对于某种软件是有意义的。如果您过于悲观,您可能会认为错误已从代码移至其正式规范(可能会有一些“错误”,因为将软件的预期行为形式化是困难且容易出错的)。


3

我偶然发现了这个问题,并且我认为此链接可能很有趣:

阿斯特雷的工业应用

证明空客公司在2003年使用的代码超过13万行的系统中没有RTE似乎并不坏,而且我想知道有人会说这不是真实世界吗?


2

否。为此,普遍的谚语是:“理论上,理论和实践是相同的,而实践中则不是。”

一个非常简单的例子:错别字。

实际上,通过单元测试运行代码几乎可以立即发现这些问题,而一系列内聚的测试将不需要任何正式的证明。所有用例-好的,坏的,错误的和边缘的情况-都应在单元测试中枚举,最终比与代码分开的任何此类证明更好地证明代码是正确的。

特别是如果需求发生变化,或者更新了算法以修复错误-正式证明更有可能以过时而告终,这与代码注释经常会得到相同。


3
错误。任何单元测试都不可能覆盖所有可能的参数范围。想象一下以这种方式对编译器进行“单元测试”,确保没有通过更改语义。
SK-logic

3
单元测试不是圣杯……
Ryathal 2011年

1
@Winston Ewert,有经过验证的编译器(以及更多经过验证的汇编器)。与软件相比,对硬件进行正式验证的频率要高得多。参见此处:gallium.inria.fr/~xleroy/publi/compiler-certif.pdf
SK-logic

1
@ SK-logic,是的,有些玩具编译器被证明可正确用于学术目的。但是人们实际使用的编译器呢?我怀疑大多数编译器都使用各种形式的自动化测试进行了检查,并且几乎没有形式上正确的证明。
温斯顿·埃韦特

1
@Winston Ewert,正确性证明是实用的,并在现实生活中被广泛使用。大多数现代主流语言都不实用。我希望他们都会死掉,因此正确性证明的价值将来会增加。
SK-logic

1

我认为由于暂停问题而对正确性证明施加的限制可能是使正确性证明成为主流的最大障碍。


8
暂停问题表明我们无法确定是否有任何程序暂停。这些程序可以做一些奇怪的事情,例如测试每个整数以查看它是否是梅森素数。我们在普通程序中不这样做!
Casebash

1
@Casebash,问题是是否有有用的程序子集可以解决暂停问题。多数民众赞成在任何一种方式都还不清楚。即我们可以限制程序,以便在不破坏我们执行有用任务的能力的情况下进行诸如测试每个整数之类的事情吗?
温斯顿·埃韦特

1

每个人都已经使用了它。每次使用编程语言的类型检查时,基本上都是在数学上证明程序的正确性。这已经很好地工作了-它只需要您为使用的每个函数和数据结构选择正确的类型。类型越准确,您得到的检查就越好。编程语言中可用的现有类型已经具有足够强大的工具来描述几乎所有可能的行为。这适用于每种可用的语言。C ++和静态语言仅在编译时进行检查,而像python这样的动态语言则在程序运行时进行检查。支票仍然以所有这些语言存在。(例如,c ++已经像haskell一样支持副作用检查,


关于C ++中的副作用,您是指const正确性吗?
温斯顿·埃韦特

是的,const + const成员函数。如果所有成员函数都是const,则对象中的所有数据都是不可修改的。
tp1

如果您使用mutable或,它们仍然可以修改const_cast。我当然可以看到您在此处绘制的联系,但是两种方法的风格对我来说似乎完全不同。
温斯顿·埃韦特

好吧,这就是为什么您需要选择使用它-总是有解决它的方法。但是重要的一点是如何使编译器检查该区域中的问题。
tp1
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.