3

我是 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;
}
4

1 回答 1

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,在程序的预状态中,介于0和之间n。这与我之前所说的相结合,是 jessie 无法证明这一点的原因之一。

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

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;
}
于 2013-04-18T14:18:41.697 回答