我用frama-c测试这个小程序,我不断收到同样的错误。我不确定这意味着什么。我特别想知道一切意味着什么。
以下是ACSL注释的相关代码:
// assuming n is nonnegative and even, f returns n
/*@ requires n>=0;
*/
int f(int n) {
int i=0;
while (i<n) {
i+=2;
}
//@ assert i==n;
return i;
}
以下是我尝试测试代码时终端所说的内容:
[wp] warning: Missing RTE guards
p3.c:9:[wp] warning: Missing assigns clause (assigns 'everything' instead)
[wp] 1 goal scheduled
[wp] [Alt-Ergo] Goal typed_f_assert : Unknown (Qed:8ms) (54ms)
[wp] Proved goals: 0 / 1
Alt-Ergo: 0 (unknown: 1)
答案 0 :(得分:4)
首先,您的财产不是正确的,因为您不需要n
甚至在函数的前提条件下。因此,我将向您展示如何在循环体中使用i += 1
来证明程序的变体。
assigns
子句是WP要求您为每个循环和每个外部函数调用指定的内容。它必须包含可由循环(或函数)修改的所有存储器位置(即变量)的列表。它需要这样才能知道循环中不修改了其他所有内容。特别是,在这个程序中,WP需要知道虽然i
的值可能在循环中发生变化,但n
的值不会改变。但是,如果您没有告诉它是这种情况,它会假定循环可以分配&#34;所有内容&#34;,包括n
。
要指定此项,您可以在循环上方插入以下注释:
/*@ loop assigns i; */
如果您尝试证明这一点(在GUI中),您将看到WP可以验证此分配条款。
但是,循环后的断言仍然无法用此证明。这是因为除了一个assigns子句之外,每个循环还必须有一个循环不变:在循环的每次迭代之前和之后总是为真的东西。选择正确且足够强大的循环不变量是一种黑暗的艺术,但一般来说,不变量必须是这样的东西,一旦循环条件为假并且循环终止,就允许我们在循环之后结束断言。
也就是说,我们希望具有以下属性的公式I
作为不变量:
I && !(i < n) ==> i == n
因此,一个不错的选择是循环不变i <= n
,因为如果i <= n
但是我们知道i < n
不是是真的(因为循环已停止迭代) ,i
必须等于n
。
将所有内容放在一起,这是一个带注释的程序变体:
/*@ requires n>=0;
*/
int f(int n) {
int i=0;
/*@ loop assigns i;
@ loop invariant i <= n;
*/
while (i<n) {
i += 1;
}
//@ assert i==n;
return i;
}
这会自动验证:
[wp] warning: Missing RTE guards
[wp] 4 goals scheduled
[wp] Proved goals: 4 / 4
Qed: 4