我有这段C代码:
while(p->next) p = p->next;
我想证明无论列表有多长,在此循环结束时,
p->next
等于 NULL
,且 EIP 指向此循环后的下一条指令。但是我不知道怎样证明在 Isabelle/HOL 中的循环。
我有这段C代码:
while(p->next) p = p->next;
p->next
等于 NULL
,且 EIP 指向此循环后的下一条指令。一组工具(免责声明:我是后者的作者),可以将C代码导入Isabelle/HOL中以进行进一步的推理,这些工具包括Michael Norrish的C Parser和AutoCorres。
使用AutoCorres,我可以解析以下C文件:
struct node {
struct node *next;
int data;
};
struct node * traverse_list(struct node *list)
{
while (list)
list = list->next;
return list;
}
使用以下指令将其转换为 Isabelle:
theory List
imports AutoCorres
begin
install_C_file "list.c"
autocorres [ts_rules = nondet] "list.c"
接下来,我们可以证明一个 Hoare 三元组,它声明对于任何输入状态,函数的返回值将为 NULL
:
lemma "⦃ λs. True ⦄ traverse_list' l ⦃ λrv s. rv = NULL ⦄"
(* Unfold the function definition. *)
apply (unfold traverse_list'_def)
(* Add an invariant to the while loop. *)
apply (subst whileLoop_add_inv [where I="λnext s. True"])
(* Run a VCG, and solve the conditions using the simplified. *)
apply wp
apply simp
done
这是一个部分正确性定理,有点陈述了您所要求的内容。(特别地,它表明如果函数终止,且如果它不出错,那么后置条件是真实的)。
要进行更完整的证明,您需要在上述内容中增加一些内容:
您需要知道列表是有效的;例如,中间节点不指向无效地址(例如,未对准的地址),并且列表不形成循环(意味着while循环永远不会终止)。
您还需要证明终止性。这与上面的第二个条件有关,但您可能仍然需要证明它为什么是正确的。(一种典型的方法是说列表的长度总是减少,因此循环最终将终止)。
AutoCorres没有指令指针的直接概念(通常这些概念只存在于汇编级别),但是终止证明类似。
AutoCorres提供了一些关于链表推理的基本库,在中,这将是一个很好的起点。