使用Jessie插件和Frama-C进行验证问题

时间:2013-04-18 13:59:53

标签: verification frama-c

我是Frama-C的新手,我想要正确学习ACSL语法。我有这个虚拟示例,Jessie插件无法验证第9行和第12行。我错过了什么吗?要验证的函数(相等)将检查两个数组(a和b)在每个索引处是否具有相同的值:

/*@
     requires \valid_range(a,0,n-1);
     requires \valid_range(b,0,n-1);
     requires n >= 0;
     requires i >= 0 && i <= n;
     assigns i;
     behavior all_equal:
         assumes i == n;
         ensures \result == 1;
     behavior some_not_equal:
        assumes i != n;
        ensures \result == 0;
*/
int equal(int a[], int n, int b[], int i) {
  /*@ 
    loop invariant 0 <= i <= n;
    loop assigns i;
    loop variant n-i;
  */  
  for (i = 0; i < n; i++) {
    if (a[i] != b[i])
      return 0;
  }
  return 1;
}

1 个答案:

答案 0 :(得分:2)

这里有一些不正确的事情:

behavior all_equal:
     assumes i == n;
     ensures \result == 1;
 behavior some_not_equal:
    assumes i != n;
    ensures \result == 0;

assumes子句中,所有变量都在函数的前置状态中计算。这意味着如果您有两个相等的大小n数组,并假设i0(它不可能,请参阅下面的解释),i == n将始终失败,除非数组的大小为0

另一件事:您似乎使用i作为循环控制的变量,在循环开始时将其设置为0,但是在您的注释中,您在前面说i该计划的状态介于0n之间。这与我之前所说的相结合是杰西无法证明这一点的原因之一。

最后,你无法证明这一点的主要原因是你缺少一个必要的循环不变量,它保证了当前迭代之前的所有数组索引的两个数组是相等的:

loop invariant loop invariant \forall integer k; 0 <= k < i ==> a[k] == b[k];

使用此不变量,您现在可以更好地指定您的行为。解决问题的正确方法是:

/*@
     requires \valid_range(a,0,n-1);
     requires \valid_range(b,0,n-1);
     requires n >= 0;
     behavior all_equal:
         assumes \forall integer k; 0 <= k < n ==> a[k] == b[k];
         ensures \result == 1;
     behavior some_not_equal:
        assumes \exists integer k; 0 <= k < n  && a[k] != b[k];
        ensures \result == 0;
*/
int equal(int a[], int n, int b[]) {
  int i = 0;
  /*@ 
    loop invariant 0 <= i <= n;
    loop invariant \forall integer k; 0 <= k < i ==> a[k] == b[k];
    loop assigns i;
    loop variant n-i;
  */  
  for (i = 0; i < n; i++) {
    if (a[i] != b[i])
      return 0;
  }
  return 1;
}