假设我们有这样的数据结构:
#typedef struct
{
int C_Field;
}C;
#typedef struct
{
C B_Array[MAX_SIZE];
}B;
#typedef struct
{
B A_Array[MAX_SIZE];
}A;
在以下示例中,Frama-C似乎没有为C类结构的字段分配位置:
/*@
assigns Arg->A_Array[0..(MAX_SIZE - 1)].B_Array[0..(MAX_SIZE - 1)].C_Field;
*/
void Initialize (A * Arg);
上面的注释是否可以被Frama-C接受?
代码详述如下。主要目标是将字段C_Field重置为0:
/*@ predicate
ResetB (B * Arg) =
\forall integer Index; 0<= Index < MAX_SIZE ==>
Arg -> B_Array[Index].C_Field == 0;
*/
//@ assigns * Arg;
// Even I tried this:
//@ assigns Arg -> A_Array[0..(MAX_SIZE - 1)];
void Initialize (A * Arg)
{
/*@ loop invariant 0 <= Index <= MAX_SIZE;
loop invariant ResetB(&(Arg->A_Array[Index]));
loop assigns Index, Arg -> A_Array[0..(MAX_SIZE - 1)];
*/
for (int Index = 0; Index < MAX_SIZE; Index++)
{
Reset(&(Arg -> A_Array[Index]));
}
}
/*@ assigns Arg -> B_Array[0..(MAX_SIZE - 1)];
ensures ResetB(Arg);
*/
void Reset(B * Arg)
{
/*@ loop invariant 0 <= Index <= MAX_SIZE;
loop invariant \forall integer i; 0<= i < Index ==>
Arg -> B_Array[i].C_Field == 0;
loop assigns Index, Arg -> B_Array[0..(MAX_SIZE - 1)];
*/
for (int Index = 0; Index < MAX_SIZE; Index++)
{
Arg -> B_Array[Index].C_Field = 0;
}
}
函数Reset的合同已经满足,但函数Initialize的合同不是。如何写出正确的&#34;分配&#34;对于Initialize的合同?
答案 0 :(得分:2)
假设您正在使用插件WP(请参阅上面的评论),您的主要问题是您没有在loop assigns
函数中为您的循环编写Initialize
。 loop assigns
对于要使用WP的函数中出现的每个循环都是必需的。此外,如果您的合同有ensures
条款,则您很可能需要loop invariant
,再次针对所分析代码中的每个循环。
<强>更新强>
使用您提供的代码和frama-c Silicon,唯一未通过frama-c -wp file.c
证明的是Initialize
中关于ResetB
的循环不变量。它未被证明的原因是它是错误的。真正的不变量应该是\forall integer i; 0<=i<Index ==> ResetB(&(Arg->A_Array[i]))
。通过以下完整示例,所有内容都已解除,至少在Silicon:
#define MAX_SIZE 100
typedef struct
{
int C_Field;
int D_Field;
}C;
typedef struct
{
C B_Array[MAX_SIZE];
}B;
typedef struct
{
B A_Array[MAX_SIZE];
}A;
/*@ predicate
ResetB (B * Arg) =
\forall integer Index; 0<= Index < MAX_SIZE ==>
Arg -> B_Array[Index].C_Field == 0;
*/
void Reset(B * Arg);
// @ assigns * Arg;
// Even I tried this:
//@ assigns Arg -> A_Array[0..(MAX_SIZE - 1)];
void Initialize (A * Arg)
{
/*@ loop invariant 0 <= Index <= MAX_SIZE;
loop invariant \forall integer i; 0<=i<Index ==> ResetB(&(Arg->A_Array[i]));
loop assigns Index, Arg -> A_Array[0..(MAX_SIZE - 1)];
*/
for (int Index = 0; Index < MAX_SIZE; Index++)
{
Reset(&(Arg -> A_Array[Index]));
}
}
/*@ assigns Arg -> B_Array[0..(MAX_SIZE - 1)];
ensures ResetB(Arg);
*/
void Reset(B * Arg)
{
/*@ loop invariant 0 <= Index <= MAX_SIZE;
loop invariant \forall integer i; 0<= i < Index ==>
Arg -> B_Array[i].C_Field == 0;
loop assigns Index, Arg -> B_Array[0..(MAX_SIZE - 1)];
*/
for (int Index = 0; Index < MAX_SIZE; Index++)
{
Arg -> B_Array[Index].C_Field = 0;
}
}