我是Frama-C的新手,我想要正确学习ACSL语法。我有这个虚拟示例,Jessie插件无法验证第9行和第12行。我错过了什么吗?要验证的函数(相等)将检查两个数组(a和b)在每个索引处是否具有相同的值:
/*@
requires \valid_range(a,0,n-1);
requires \valid_range(b,0,n-1);
requires n >= 0;
requires i >= 0 && i <= n;
assigns i;
behavior all_equal:
assumes i == n;
ensures \result == 1;
behavior some_not_equal:
assumes i != n;
ensures \result == 0;
*/
int equal(int a[], int n, int b[], int i) {
/*@
loop invariant 0 <= i <= n;
loop assigns i;
loop variant n-i;
*/
for (i = 0; i < n; i++) {
if (a[i] != b[i])
return 0;
}
return 1;
}
答案 0 :(得分:2)
这里有一些不正确的事情:
behavior all_equal:
assumes i == n;
ensures \result == 1;
behavior some_not_equal:
assumes i != n;
ensures \result == 0;
在assumes
子句中,所有变量都在函数的前置状态中计算。这意味着如果您有两个相等的大小n
数组,并假设i
是0
(它不可能,请参阅下面的解释),i == n
将始终失败,除非数组的大小为0
另一件事:您似乎使用i
作为循环控制的变量,在循环开始时将其设置为0,但是在您的注释中,您在前面说i
该计划的状态介于0
和n
之间。这与我之前所说的相结合是杰西无法证明这一点的原因之一。
最后,你无法证明这一点的主要原因是你缺少一个必要的循环不变量,它保证了当前迭代之前的所有数组索引的两个数组是相等的:
loop invariant loop invariant \forall integer k; 0 <= k < i ==> a[k] == b[k];
使用此不变量,您现在可以更好地指定您的行为。解决问题的正确方法是:
/*@
requires \valid_range(a,0,n-1);
requires \valid_range(b,0,n-1);
requires n >= 0;
behavior all_equal:
assumes \forall integer k; 0 <= k < n ==> a[k] == b[k];
ensures \result == 1;
behavior some_not_equal:
assumes \exists integer k; 0 <= k < n && a[k] != b[k];
ensures \result == 0;
*/
int equal(int a[], int n, int b[]) {
int i = 0;
/*@
loop invariant 0 <= i <= n;
loop invariant \forall integer k; 0 <= k < i ==> a[k] == b[k];
loop assigns i;
loop variant n-i;
*/
for (i = 0; i < n; i++) {
if (a[i] != b[i])
return 0;
}
return 1;
}