Frama-C阶函数

时间:2018-11-10 10:24:51

标签: c frama-c

我正在尝试使用ACSL语言用Frama-C证明我的排序功能“顺序”的正确性。我还有一个附加的“交换”功能来置换数组“ t”的两个值。

编辑: 我更新了代码。

/*@ 
    requires \valid (t+ (0..(l-1)));
    requires l > 0;
    requires i<l && j<l && i>=0 && j>=0;
    assigns t[i], t[j];
    ensures t[j] == \old(t[i]);
    ensures t[i] == \old(t[j]);
*/
void swap(int *t, int l, int i,int j){
  int tmp;
  tmp = t[i];
  t[i] = t[j];
  t[j] = tmp;
  return;
}

/*@ 
    requires \valid (t+ (0..(l-1)));
    requires l > 0;
    ensures \forall integer k; (0 <= k < l-1) ==> t[k] <= t[k+1]; 
*/
void order(int *t, int l) {
  int i;
  int j;
/*@
    loop assigns i, t[0 .. l-1];
    loop invariant 0<=i<l && i>=0;
    loop invariant \forall integer k; (0 <= k<=i) ==> t[k] <= t[k+1]; 
    loop variant l-i;


*/
  for (i=0;i<l;i++) {

/*@
    loop assigns j, t[0 .. l-1];
    loop invariant i<=j<l && i>=0 && j>=0;
    loop invariant  \forall  integer k; (0 <= k <= j)  ==> (t[k] <=  t[k+1]);
    loop variant l-j;

*/
    for (j=i; j<l; j++) {

      if (t[i] > t[j]){
    /*@ assert t[i] > t[j] && i<l && j<l && i>=0 && j>=0 ; */
    swap(t, l, i, j);
    /*@ assert t[i] < t[j] && i<l && j<l && i>=0 && j>=0 ; */
      }
    }
  }
}

enter image description here 感谢您的帮助!

1 个答案:

答案 0 :(得分:3)

与使用WP时一样,至关重要的是,被证明函数调用的所有函数都必须带有带有assigns子句的协定。此外,所述函数在证明下的所有循环都必须具有loop assigns子句。如果不是这种情况,WP会得出结论,内存状态的任何部分都可能被调用修改(即循环),因此在相应的指令之后它将无法说出有意义的任何内容。

因此,至少,您应该通过以下方式添加/替换现有子句:

  • swap的合同中,条款assigns t[i], t[j];
  • 在外循环的循环注释中,子句loop assigns i, t[0 .. l-1];
  • 在内部循环的循环注释中,子句loop assigns j, t[i .. l-1];

作为关于loop assigns的旁注:

  • 他们必须描述从第一次进入循环到当前步骤的所有可能的修改(因此t[i], t[j]是不够的,因为在当前j之前可能还发生了其他交换) 。
  • 循环索引(此处为ij)必须是循环分配的一部分,尽管很容易忽略它并想知道WP为什么不满意。

请注意,您的注释可能还有其他问题,但这是最明显的问题,在尝试证明更深层的功能特性之前,拥有适当的assigns子句可能是最重要的事情。