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

Frama-C无法验证assign子句求助:函数合约证明失败排查

解决Frama-C WP无法证明assign子句的问题

我来帮你分析下为什么Frama-C的WP插件没法证明这个循环的assign子句,其实问题出在循环不变量的逻辑精度上,咱们一步步拆解:

问题根源

你的循环不变量 test: \forall int j; (n>j>i ==> a[j]==0); 只覆盖了大于当前i的数组元素,但每次循环修改的是a[i]——这个位置并不在当前不变量的覆盖范围内。WP需要明确知道每次循环修改的元素在操作后满足的状态,否则无法验证assign子句的正确性。

另外,原assign子句a[0..n-1]虽然整体上描述了循环最终修改的范围,但缺乏每次循环的精准修改信息,也会给WP的证明带来阻碍。

修改方案

调整循环不变量和assign子句,让逻辑更精准:

/*@ 
@ requires n>0; 
@ requires \valid(a+(0..n-1)); 
@ ensures \forall int i; (0 <= i < n ==> a[i]==0); 
@*/ 
void f(int n, float *a) { 
/*@ 
@ loop invariant \forall int j; (i < j < n ==> a[j] == 0);
@ loop invariant i >= -1; // 明确循环变量i的下界,循环结束后i=-1
@ loop assigns i, a[i]; // 精准声明每次循环只修改a[i]和i
@*/ 
for (int i=n-1; i>=0; i--) { 
    a[i] = 0; 
} 
}

为什么这样修改有效

  1. 精准的assign子句:a[i]明确告诉WP,每次循环只会修改当前i对应的数组元素,避免了宽泛范围带来的证明模糊性。
  2. 完善的循环不变量:
    • 第一个不变量保证了所有大于i的元素已经被置0,初始时i=n-1,没有元素满足i<j<n,不变量成立;每次循环i减1,刚被置0的a[i]会进入下一轮循环的j>i范围,不变量得以维护。
    • 第二个不变量i >= -1明确了i的合法范围,循环结束后i=-1,此时第一个不变量覆盖了0<=j<n的所有元素,正好匹配函数的ensures条件。

这样调整后,WP就能顺利完成assign子句以及所有合约的证明了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 03:51:21