我经常听到有人说过,由于赖斯定理,您无法编写程序来捕获Web浏览器,文字处理器或操作系统中的错误:赖斯定理的任何语义属性都是不确定的。
但是,我不确定这在多大程度上适用于像操作系统这样的真实程序。这些类型的程序是否需要图灵完整性的全部力量?是否可以使用这些应用程序编写更简单的计算模型(例如PR)?如果是这样,在何种程度上可以确定程序正确性?
我经常听到有人说过,由于赖斯定理,您无法编写程序来捕获Web浏览器,文字处理器或操作系统中的错误:赖斯定理的任何语义属性都是不确定的。
但是,我不确定这在多大程度上适用于像操作系统这样的真实程序。这些类型的程序是否需要图灵完整性的全部力量?是否可以使用这些应用程序编写更简单的计算模型(例如PR)?如果是这样,在何种程度上可以确定程序正确性?
Answers:
您当然可以编写捕获错误的程序-有大量活跃的人编写程序来实现此目的。然而,赖斯定理阻止您进行的工作是编写既完善又完整的bug捕捉程序(即,捕获某个类的所有bug且没有误报)。
也就是说,对计算模型的幼稚限制实际上对改善程序分析的实用性没有太大帮助。原因是您可以通过翻转while循环来获得执行“几乎相同的事情”的程序
while P do
C
进入具有较大迭代常数的for循环中:
for i = 0 to BIGNUM do
if P then
C
else
break
现在,该程序甚至不需要原始递归的全部功能(因为可以将for循环宏扩展为巨大的嵌套if-then-else语句),但是在大多数实际情况下,它的行为与以前相同。请注意,它确实在理论上有助于确定性-该程序是完整程序,因此您可以通过运行该程序并查看会发生什么来回答问题。这不是我们真正想要的,它比运行程序更快地获得答案-引入的人工终止实际上并没有在实践中帮助程序分析,因为由于实际程序逻辑中的错误而导致错误发生,并且我们没有一点都没有触及。
此外,在编程语言中添加抽象工具可能从根本上加剧分析问题的复杂性,同时使在实践中验证程序更容易。例如,用自然数证明简单类型的lambda演算的终止要求归纳为,但是通过添加类型多态性,您可以获得System F,其终止证明与二阶算术的一致性一样强。但是,实际上,用F编写的程序更容易验证,因为二阶量化的模块化特性使编写结构化程序和正确性证明变得更加容易。
由于您询问了诸如操作系统之类的真实程序的程序正确性,您可能会对seL4项目(journal,pdf, Conference)感兴趣。
NICTA团队采用了第三代微内核,该内核由8700行C语言和600行汇编程序组成,这些内核是根据Haskell中的抽象规范实现的。他们提供了经过机器检查的正式证明(在Isabelle / HOL中),证明该实现严格遵循规范。从而证明他们的程序没有错误。
因此,就像暂停问题一样,尽管通常无法解决该问题,但可以针对某些特定情况解决它。在这种情况下,尽管您不能证明任意C代码都没有错误,但是在seL4微内核的情况下,他们可以做到。
您提出的问题实际上是完全不同的。
但是,我不确定这在多大程度上适用于像操作系统这样的真实程序。这些类型的程序是否需要图灵完整性的全部力量?
图灵完整的计算模型几乎不需要花费什么。例如,带有计数器的各种模型可以模拟图灵机。如果您认为您的软件需要两个以上可以任意操作的计数器,则您使用的是图灵完整语言。尽管机器整数是先验有界的,但堆分配的数据结构通常不是。如果您的软件需要列表,树和其他动态分配的数据,则您使用的是图灵完整语言。
是否可以使用这些应用程序编写更简单的计算模型(例如PR)?如果是这样,在何种程度上可以确定程序正确性?
重要的是要认识到我们不想检查软件的任意属性。检查非常具体,狭窄的属性(没有缓冲区溢出,没有空指针取消引用,没有无限循环等)极大地提高了软件的质量和可用性。从理论上讲,此类问题仍无法确定。在实践中,专注于特定属性使我们能够发现程序中经常可以用来解决问题的结构。
特别是,您可以将原始问题修改为
是否可以在非图灵完整模型中有效分析我的软件?
抽象是一个模型,其中包括原始软件的行为以及可能的许多其他行为。有一些模型,例如单柜台机器或下推系统,它们的图灵功能还不完善,我们可以进行分析。使用自动化工具进行程序验证的标准方法是在这种模型中构造一个抽象,并对其进行算法检查。
在某些应用程序中,人们会关心其硬件或软件的复杂特性。硬件公司希望其芯片正确执行算术算法,而汽车和航空电子公司则希望得到可证明正确的软件。如果那么重要,那么最好是使用(训练有素的)人。