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

Frama-C提示缺失assigns子句(默认assigns 'everything')问题咨询

解决Frama-C WP插件的两个常见警告:Missing RTE Guards和Missing Assigns Clause

我来帮你拆解这两个警告,以及你困惑的assigns 'everything'到底是什么意思:

1. 第一个警告:Missing RTE guards

这个提示来自Frama-C的WP(Weakest Precondition)插件,意思是你的代码缺少运行时错误(Run-Time Error,RTE)的防护注解。

具体到你的代码:循环里的i += 2操作,WP默认会检查整数溢出的可能性——哪怕你假设n是非负偶数,但如果n大到让i加2后超出int类型的取值范围,就会触发溢出错误。插件提醒你要么显式排除这种风险,要么添加防护条件。

解决办法:可以在函数的requires注解里加上n <= INT_MAX(记得先包含头文件#include <limits.h>),明确限制n的最大值不会导致溢出。

2. 第二个警告:Missing assigns clause(对应你提到的assigns 'everything')

这是WP插件的核心要求之一:它需要明确知道你的函数会修改哪些内存位置。如果你完全没写assigns注解,WP会默认这个函数可以修改'everything'——也就是所有内存区域(包括全局变量、堆内存、其他局部变量等)。

这种默认行为会让验证变得非常宽泛,不仅降低效率,还可能导致验证结果不准确。而你的函数f里,唯一被修改的只有局部变量i,所以必须显式告诉WP这一点。

解决办法:在函数的ACSL注解里添加assigns i;,明确声明这个函数只会修改局部变量i,不会触碰其他任何内存。

修改后的完整可验证代码

#include <limits.h>

// 假设n为非负偶数,f返回n
/*@ 
  requires n >= 0;
  requires n <= INT_MAX;  // 防止i += 2时发生整数溢出
  assigns i;              // 明确函数仅修改局部变量i
  ensures \result == n;   // 用ensures替代单独的assert,更符合ACSL规范
*/
int f(int n) {
  int i = 0;
  while (i < n) {
    /*@ loop invariant i >= 0;
        loop invariant i <= n;
        loop invariant i % 2 == 0;  // 每次加2,i始终是偶数,匹配n为偶数的假设
        loop variant n - i;         // 循环变体:证明循环一定会终止(值不断减小至0)
    */
    i += 2;
  }
  //@ assert i == n;
  return i;
}

额外补充

  • 添加loop invariant和loop variant是帮WP更好地验证循环的正确性:loop variant用来证明循环必然终止,loop invariant描述循环过程中始终成立的属性。
  • 如果你的函数涉及全局变量或指针,assigns里要列出所有被修改的对象,比如assigns global_counter, *ptr, i;。
  • 为什么assigns 'everything'不好?因为WP会假设函数可能修改任何内存,这会让它在验证后置条件时,不得不考虑所有可能的内存修改对结果的影响,很可能导致验证失败,或者需要更多不必要的注解来排除干扰。

内容的提问来源于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.22 10:05:01