【问题标题】:Frama-C acsl max example from manual not working手册中的 Frama-C acsl max 示例不起作用
【发布时间】:2020-05-11 17:29:14
【问题描述】:

我相信我遗漏了一些明显的东西,但我已经尝试了很多,但我没有设法找到问题的根源。

我正在关注 Frama-C 的 acsl guide。 有这个介绍性示例说明如何验证在数组中找到最大值的正确性:

/*@ requires n > 0;
    requires \valid(p+ (0 .. n-1));
    ensures \forall int i; 0 <= i <= n-1 ==> \result >= p[i];
    ensures \exists int e; 0 <= e <= n-1 && \result == p[e];
*/
int max_seq(int* p, int n) {
  int res = *p;
  for(int i = 0; i < n; i++) {
    if (res < *p) { res = *p; }
    p++;
  }
  return res;
}

但是,运行 frama-c -wp -wp-prover alt-ergo samenum.c -then -report 我得到:

[wp] Warning: Missing RTE guards
[wp] samenum.c:8: Warning: Missing assigns clause (assigns 'everything' instead)
[wp] 2 goals scheduled
[wp] [Alt-Ergo] Goal typed_max_seq_ensures_2 : Timeout (Qed:1ms) (10s)
[wp] [Alt-Ergo] Goal typed_max_seq_ensures : Timeout (Qed:2ms) (10s)
[wp] Proved goals:    0 / 2
  Alt-Ergo:        0  (interrupted: 2)
[report] Computing properties status...

--------------------------------------------------------------------------------
--- Properties of Function 'max_seq'
--------------------------------------------------------------------------------

[    -    ] Post-condition (file samenum.c, line 3)
            tried with Wp.typed.
[    -    ] Post-condition (file samenum.c, line 4)
            tried with Wp.typed.
[    -    ] Default behavior
            tried with Frama-C kernel.


似乎 alt-ergo 在证明该属性之前就超时了。值得一提的是,我尝试了更高的超时时间,但它仍然不起作用。

我正在使用:

  • frama-c:19.1
  • 为什么 3:1.2.0
  • alt-ergo:2.3.2

我在 Ubuntu 18.04 上运行它,在运行命令之前我运行:why3 config --detect 以确保为什么Why3 知道 alt-ergo。

有什么想法吗?任何人都可以验证这是示例不起作用吗? 任何帮助将不胜感激!

【问题讨论】:

    标签: frama-c alt-ergo


    【解决方案1】:

    这个迷你教程是很久以前写的,并不是最新的。该网站的新版本应在未来几个月内出现。基本上,这个合约,以及@iguerNL 指向的循环的不变量是要使用 Jessie 插件而不是 Frama-C 的 WP 插件来验证的。这两个插件的不同之处在于,Jessie 不需要 assigns 子句用于循环和函数,而 WP 需要它们。

    因此,一个完整的带注释的max_seq 函数可能是这个:

    /*@ requires n > 0; 
        requires \valid(p+ (0..n−1));
        assigns \nothing;
        ensures \forall int i; 0 <= i <= n−1 ==> \result >= p[i]; 
        ensures \exists int e; 0 <= e <= n−1 && \result == p[e]; 
    */ 
    int max_seq(int* p, int n) { 
      int res = *p; 
      //@ ghost int e = 0; 
      /*@ loop invariant \forall integer j; 0 <= j < i ==> res >= \at(p[j],Pre); 
          loop invariant \valid(\at(p,Pre)+e) && \at(p,Pre)[e] == res; 
          loop invariant 0<=i<=n; 
          loop invariant p==\at(p,Pre)+i; 
          loop invariant 0<=e<n; 
          loop assigns i, res, p, e;
          loop variant n-i;
      */ 
      for(int i = 0; i < n; i++) { 
        if (res < *p) { 
          res = *p; 
          //@ ghost e = i; 
        }
        p++; 
      } 
      return res; 
    }
    

    我们指定函数不在内存中分配任何内容,并且循环分配不同的局部变量irespe(因此保持n 不变)。

    请注意,有更多最新的教程可用于了解如何将 Frama-C 与 WP 插件一起使用。未来版本的 Frama-C 网站提到:

    【讨论】:

    • 感谢您的回答!您的代码 sn-p 工作得很好。两个小 cmets:(i)带有 WP 插件的新版本似乎要复杂得多,那为什么要更改? (ii) 官方网站有错误的文档是误导性的,我真的希望它会尽快更新。
    • 为了清楚起见,因为也许不是,WP 和 Jessie 都需要循环不变注释。唯一的区别是 WP 总是需要 assigns 注释。事实上,在一般情况下,分配的内存位置并不容易推断,并且可能导致复杂的证明义务,而自动求解器则难以处理。因此,在这里,Jessie 不需要 assigns 注释,但如果示例更复杂,则可以。 WP 总是需要它们,因此在某种程度上更加同质。
    【解决方案2】:

    您可能忘记为“for”循环添加不变量。请参阅您提供的手册中的“10.2 循环不变量”部分 (https://frama-c.com/acsl_tutorial_index.html)

    【讨论】:

    • 感谢您的提示,但即使使用不变量,它也不起作用。您能否提供一个完整的 max_seq 示例?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-22
    相关资源
    最近更新 更多