You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Frama-C无法验证goto实现的循环,while版本可正常验证

Frama-C验证:goto循环实现失败,while循环等价代码成功

环境与验证命令

  • 环境:Frama-C 24.0(基于Chromium)
  • 验证命令:frama-c -wp -wp-legacy xx.c

goto循环实现代码(无法完成验证)

#include <stdlib.h>
int r;
/*@
  requires \valid_read(a + (0 .. length-1)) && length > 0;
  assigns r;
  ensures \forall size_t off ; 0 <= off < length ==> a[off] != r;
*/
void notin(int* a, size_t length) {
  int result = 0;
  int max = 0;
  size_t i = 0;
  
assign_part:
  if (a[i] >= max) {
    max = a[i];
  }
  result = max + 1;
  i = i + 1;
 
  if (i < length) {
    goto assign_part;
  }

  r = result;
}

验证错误输出

[kernel] Parsing goto_test/while_2_goto_version.c (with preprocessing)
[wp] Warning: Missing RTE guards
[wp] goto_test/while_2_goto_version.c:14: Warning: 
  Missing assigns clause (assigns 'everything' instead)
[wp] 6 goals scheduled
[wp] [Alt-Ergo ] Goal typed_notin_assigns_part2 : Timeout (Qed:4ms) (10s)
[wp] Proved goals:    5 / 6
  Qed:             4  (3ms-10ms-30ms)
  Alt-Ergo :       1  (6ms) (44) (interrupted: 1)
[wp] goto_test/while_2_goto_version.c:8: Warning: 
  Memory model hypotheses for function 'notin':
  /*@ behavior wp_typed:
        requires \separated(a + (..), &r

while循环等价代码(验证成功)

#include <stdlib.h>
int r;
/*@
  requires \valid_read(a + (0 .. length-1)) && length > 0;
  assigns r;
  ensures \forall size_t off ; 0 <= off < length ==> a[off] != r;
*/
void notin(int* a, size_t length) {
 int result = 0;
 int max = 0;
 size_t i = 0;
 
 /*@ loop invariant 0 <= i <= length;
   @ loop invariant \forall size_t j; 0 <= j < i ==> a[j] <= max;
   @ loop invariant \forall size_t k; 0 <= k < i ==> a[k] != result;
   @ loop assigns i, result, max;
 */
 while (i < length) {
   if (a[i] >= max) {
     max = a[i];
   }
   result = max + 1;
   i = i + 1;
 }

 r = result;
}

原因分析与修复建议

Frama-C的WP插件对结构化循环(如while)的支持更完善:while版本通过loop invariant明确了循环过程中始终成立的性质,loop assigns指定了循环内会修改的变量,这些注解大幅减少了验证器需要探索的证明路径,从而顺利完成验证。

而goto形成的非结构化循环,WP无法自动识别并推导循环不变式;同时代码中缺少对goto循环内修改变量的assigns注解(错误信息也明确提示了"Missing assigns clause"),导致验证器需要尝试大量可能性,最终超时。

要让goto版本通过验证,只需手动添加对应的循环注解,在assign_part:标签前补充如下内容即可:

/*@ loop invariant 0 <= i <= length;
  @ loop invariant \forall size_t j; 0 <= j < i ==> a[j] <= max;
  @ loop invariant \forall size_t k; 0 <= k < i ==> a[k] != result;
  @ loop assigns i, result, max;
*/

内容的提问来源于stack exchange,提问作者Lebecca

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 15:27:41