Frama-C使用ensures注解证明while循环后置条件失败问题
问题根源
Frama-C的WP插件验证循环逻辑时,所有循环退出后成立的程序属性,都必须明确写在循环不变式中。WP不会自动推导循环内部的执行效果,只会检查你提供的不变式是否在循环入口成立、是否每次循环迭代后都保持成立,再结合循环退出条件(这里是count == 0)推导循环后的状态。
你当前写的循环不变式只约束了count的取值范围,完全没有提到x的取值规则。WP分析到循环结束位置时,对x的值没有任何有效约束,自然无法证明后置条件里的x == 5。
你把x=5移到循环外可以验证通过,是因为循环外的赋值属于直线控制流,WP可以直接追踪赋值效果,不需要依赖循环不变式传递状态。
修复方案
在循环不变式中补充x的取值约束即可。结合你的代码逻辑:只要执行过至少一次循环体,x就会被赋值为5;而循环初始count=3,必然会进入循环体执行,因此新增一条对应不变式:
/*@ loop invariant 0 <= count <= \at(count, Pre); loop invariant count < \at(count, Pre) ==> x == 5; // 新增约束 loop assigns accept,x,count; loop variant count; */
这条不变式的逻辑完全匹配代码执行流程:
- 首次进入循环、还未执行循环体时,
count等于初始值3,count < \at(count, Pre)不成立,蕴含式自动为真,满足不变式初始成立要求 - 每执行完一次循环体,
count比初始值小,此时x已经被赋值为5,蕴含式保持成立 - 循环退出时
count=0,必然小于初始值3,因此可以直接推导出x == 5,WP会用这个结论完成后置条件的证明
验证操作
修改完代码后,重新执行你原来的验证命令frama-c-gui -wp -rte testp4.c,即可看到后置条件、所有循环标注均显示为Valid状态。
补充提示:你定义的函数名abs和C标准库内置的绝对值函数重名,当前代码因为没有引入<stdlib.h>不会触发冲突,但编写正式验证代码时建议避开标准库函数名,减少不必要的干扰。
内容的提问来源于stack exchange,提问作者Uğur B
相关产品推荐
相关产品推荐

