我正在开发涵盖可验证 C 的 beta 5 软件基础模块。我在最后一部分,这与哈希映射上的操作有关(这需要对链表进行操作)。
https://www.cs.princeton.edu/~appel/vc/vc-0.9.5/Verif_hash.html
我有点坚持body_incr_list
。
正在验证的代码:
void incr_list (struct cell **r0, char *s) {
struct cell *p, **r;
for(r=r0; ; r=&p->next) {
p = *r;
if (!p) { *r = new_cell(s,1,NULL); return; }
if (strcmp(p->key, s)==0) {p->count++; return;}
}
}
这做了一些新的事情......一个指针的指针,以及进入循环的 p 为 null 的事实,但如果它循环,则保证有一个值。该模块给出的规范是:
Definition incr_list_spec : ident × funspec :=
DECLARE _incr_list
WITH r0: val, al: list (list byte × Z), s: val,
sigma : list byte, gv: globals
PRE [ _r0 OF tptr (tptr tcell), _s OF tptr tschar ]
PROP (list_get sigma al < Int.max_unsigned)
LOCAL (temp _r0 r0; temp _s s; gvars gv)
SEP (listboxrep al r0; cstring Ews sigma s; mem_mgr gv)
POST [ tvoid ]
PROP ( ) LOCAL ()
SEP (listboxrep (list_incr sigma al) r0;
cstring Ews sigma s; mem_mgr gv).
整个练习取决于适当的循环不变量。这是我的尝试
forward_loop (EX al':list (list byte * Z), EX r0': val,
PROP ()
LOCAL (temp _r r0'; temp _r0 r0; temp _s s; gvars gv)
SEP (
listboxrep al' r0';
cstring Ews sigma s;
mem_mgr gv;
listboxrep al' r0' -* (ALL sigma:list byte, listrep (list_incr sigma []) nullval -* listboxrep (list_incr sigma al) r0)
)).
有了这个,我能够取得一些基本进展,但我陷入了以下处理:
if (!p) { *r = new_cell(s,1,NULL); return; }
原因是现在在 SEP 子句中,我有listboxrep al' r0'
,但是为了让它越过这条线
p = *r;
我需要把它展开成data_at Ews (tptr tcell) p r0' * listrep al' p
. 同样,这不是一个大问题,但在 p 为 null 并且它创建新单元格 ( *r = new_cell(s,1,NULL); return;
) 的情况下,我得到了一个我不知道是否可以解决的证明目标。
这是因为data_at Ews (tptr tcell) p r0'
被转换成data_at Ews (tptr tcell) vret r0'
,但我们仍然只是有listrep al' p
,没有listrep al' vret
。虽然在这种情况下,al' 很可能是 [],这意味着我们有listrep [] p
,尽管我不确定可以用它做什么。如果我遵循这一点,我最终会得到以下蕴涵:
(list_cell sigma 1 (Vint (Int.repr 0)) vret *
data_at Ews (tptr tcell) vret r0' *
((EX p : val, data_at Ews (tptr tcell) p r0' * (!! (p = nullval) && emp)) -*
(ALL sigma0 : list byte,
(EX y : val, list_cell sigma0 1 y nullval * (!! (y = nullval) && emp)) -*
listboxrep (list_incr sigma0 al) r0)))%logic
|-- listboxrep (list_incr sigma al) r0
这让我相信我的不变量是不正确的......例如,如果我进行调整以将 p 设置为
EX p : val, data_at Ews (tptr tcell) p r0' * (!! (p = nullval) && emp)
那么它当然需要为nullval。但我们拥有的价值是data_at Ews (tptr tcell) vret r0'
......
所以我不知道。我很确定我需要改进我的不变量,但不知道如何!将不胜感激任何指针。