在Frama-C中证明while循环

时间:2017-11-01 13:19:49

标签: frama-c

我试图用frama-c中的指针分配来证明while循环。不幸的是,我遇到了问题。如果使用for-loop和数组表示法重写测试代码,我设法证明了这一点。有没有人对如何证明这一点有任何想法?

我想证明的代码:

/*@
 requires \valid(v+(0..n-1));
 requires v != \null;
 requires n > 0;
 assigns v[0..n-1];
 ensures \forall integer q; 0<=q<=n-1 ==> v[q]==(unsigned char)0;
*/
static void make_zero( unsigned char *v, size_t n ) {

volatile unsigned char *p = (unsigned char*)v;

      /*@
       loop invariant 0 <= n <= \at(n, Pre);
       loop invariant \forall integer j;  0 <= j < (\at(n, Pre)-n) ==> \at(p, Pre)[j] == (unsigned char)0;
       loop assigns n, p;
       loop variant n;  */

      while( n-- ){
         *p++ = 0;
      }
 }

重写代码:

/*@
loop invariant 0 <= i <= n;
loop invariant \forall integer j; 0 < j < i ==> p[j] == (unsigned char)0;
loop assigns i, p[0..n-1];
loop variant n-i;
*/

for(size_t i = 0; i<n; i++){
  p[i] = 0;
}

1 个答案:

答案 0 :(得分:3)

首先,一句话。 <{1}}前置条件v != \null是多余的,可以删除。

另一个注释,\valid(v+(0..n-1))是一个局部变量,它不在p状态的范围内。因此Pre或多或少没有意义(虽然被WP接受)。你可能意味着\at(p, Pre) - 无论如何都更简单。

其次,你的循环分配是假的。 v指向的数组的单元格也被修改。您必须将其更改为v

第三,你需要另一个循环不变量,它在assigns n, p, v[0..\at(n, Pre)-n-1]p方面表达v。否则,WP无法精确建模n编写时会发生什么,并且无法证明修改后的*p。这个不变量是loop assigns

你最后的问题是你声明p == v + (\at(n, Pre)-n)不稳定。这里不需要这样做,实际上使得证明不可能:p的值每次访问时都可能会改变。删除此限定符后,证明即告完成。

完整的参考代码:

p