了解如何使用Frama-c正确使用后置条件和循环不变量

时间:2014-11-21 00:23:16

标签: functional-testing frama-c

我试图在这个例子中证明返回值为0(如果8不在数组中)或1(如果数组为8)。


int fi8(int *array, int size) {
  int fi8 = 0;
  int i = 0;
  for(i = 0; i < length; ++i)
  {
     if(array[i] == 8)
     fi8 = 1;
  }
  return fi8;
}

我创造了前后条件:

/*@ requires 0 <= size <= 100;
@  requires  \valid(array+(0..size-1));
@  assigns \nothing;
@  ensures (\forall integer i; 0<= i < size && array[i] != 8)  ==> (\result == 0);
@  ensures (\exists integer i; (0<= i < size && array[i] == 8)) && (\result == 1);
@*/

和循环不变量,因为Frama-C基于Hoare Logic:

/*@ loop invariant 0 <= i <= length;
  @  loop invariant  fi8 == 0 || fi8 == 1;
  @  loop invariant (\forall integer i; 0<= i < size && array[i] != 8)
      ==> (fi8 == 0);
  @  loop invariant (\exists integer i; (0<= i < size && array[i] == 8)) 
      && (fi8 == 1);
  @  loop assigns i, fi8;
  @*/

我很确定我在线路上遗漏了一些东西,我试图使用forall 并存在。 我花了好几个小时试图理解,我如何正确检查,是否在阵列上分配了任何值,但我觉得我被困在这里。 我非常感谢你的帮助:)。

1 个答案:

答案 0 :(得分:3)

您的代码存在一些问题。首先,您似乎混合了sizelength。我自由地在任何地方使用size,否则这个代码甚至不会被C编译器接受,更不用说Frama-C了。其次,\forall integer i; 0<= i < size && array[i] != 8(和相应的循环不变量)不正确。从字面上看,这意味着任何整数i都验证两者i介于0 size和{{ 1}}不是array[i]。以8101给出了这个命题的一个微不足道的反例。您要表达的是,对于任何整数i如果 i介于i0之间, size不是array[i],表示为8。另一方面,\forall integer i; 0<= i < size ==> array[i] != 8连接器在&&下使用时是正确的:这次我们确实想要找到\existsii的范围内数组和array[i]==8。但是,您上次确认的第二个&&不正确:您要说的是如果有这样的i,那么\result == 1,因此你必须在这里有一个含义:(\exists integer i; 0<= i < size && array[i] == 8) ==> (fi8 == 1)

最后一个问题是你的循环不变量。您正在重新使用它作为量化变量,而它已经是C变量,这通常不是一个好主意。事实上,这是一个真正的问题,因为您要表达的属性是,只要我们在80i之间没有看到fi8==0(并且,如果看到8fi8==1),i是C变量。如果您在量化中使用j,请参阅

 loop invariant (\forall integer j; 0<= j < i ==> array[j] != 8) ==> (fi8 == 0);
 loop invariant (\exists integer j; 0<= j < i && array[j] == 8) ==> (fi8 == 1);

所有证明义务均已解除。