了解Frama-C逻辑标签

时间:2013-09-04 13:14:32

标签: frama-c

当我尝试使用默认逻辑标签LoopEntry和LoopCurrent时,我遇到了一些麻烦。这是一个简单的例子,我使用的不同证明器(alt-ergo,coq,cvc3,z3)无法证明:

/*@ requires n > 0;*/
void f(int n){
    int i = 0;
    /*@ loop invariant \at(i,LoopEntry) == 0;
      @ loop invariant \at(i,LoopCurrent) >= \at(i,LoopEntry);
      @ loop invariant 0 <= i <= n;
      @ loop assigns i;
      @ loop variant n-i;
    */
    while(i < n){
        i++;
    }
}

特别是,没有证明第一和第二不变量(其他不存在问题)。现在,如果我通过在i的声明/定义之后添加标签“label”来修改这个简单的例子,并且如果我引用该标签,并通过Here更改LoopCurrent(这给出了这个片段:

/*@ requires n > 0;*/
void f(int n){
    int i = 0;
    label : ;
    /*@ loop assigns i;
      @ loop invariant \at(i,label) == 0;
      @ loop invariant \at(i,Here) >= \at(i,label);
      @ loop invariant 0 <= i <= n;
      @ loop variant n-i;
    */
    while(i < n){
        i++;
    }
}

现在一切都证明了。

我发现有关Acsl默认逻辑标签的文档很容易理解,我希望第一个例子被证明是第二个。你能解释一下问题的来源吗?

小豆

PS1:在循环子句中使用Pre时会引用什么?第一次循环迭代或前一次迭代之前的状态??

PS2:我正在使用Frama-C Fluorine,但也许我没有为每次小更新升级

1 个答案:

答案 0 :(得分:4)

氟化物中的WP确实不支持

LoopCurrentLoopEntry。这已在开发版本中修复(请参阅http://bts.frama-c.com/view.php?id=1353),并应出现在下一版本中。

关于其他预定义标签,

  • Pre始终引用函数开头的状态。
  • Old只能在合同中使用,并且指的是此合同的前置状态(即评估requiresassumes子句的状态)。因此,对于函数契约,它等效于Pre,但对于语句契约,不等于(除非您签订了包含函数主块的契约)。
  • Here表示评估相应注释的程序点。在合同中,其含义取决于它出现的条款。
  • Post只能在ensuresassignsallocatesfrees条款中使用,并且可以参考合同末尾的州。