2017-04-27 31 views
2

假设我们有这样的数据结构:ACSL“分配”注解为内结构和的C代码字段

#typedef struct 
{ 
int C_Field; 
}C; 

#typedef struct 
{ 
C B_Array[MAX_SIZE]; 
}B; 

#typedef struct 
{ 
B A_Array[MAX_SIZE]; 
}A; 

似乎邮资-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; 
} 
} 

功能复位的合同是满意的,但功能初始化的合同是没有的。如何为Initialize的合同写一个正确的“赋值”?

+1

你的问题有点不清楚。 Frama-C Silicon(最新的稳定版本)可以很好地解析'assigns'(只要'typedef'前面的'#'被移除并给出'MAX_SIZE'的定义)。您能否描述一下您使用此代码所做的尝试,以及Frama-C给出的结果与预期的结果有何不同? – Virgile

+0

感谢您的回复。我们的主要目标是将字段C_Field重置为0.上面的代码详细阐述如下: – Rocolife

+0

欢迎使用StackOverflow。这应该是C语法?然后修复语法错误和/或预处理器/编译器语法的奇怪混淆。我认为@Virgile的意思是一样的。然后提供[mcve]。否则,删除C标签。请考虑参加[旅游]。 – Yunnosch

回答

2

假设您使用插件WP(请参阅上面的注释),您的主要问题是您没有在Initialize函数中为您的循环编写loop assigns。对于要在其中使用WP的函数中出现的每个循环,都必须使用loop assigns。另外,如果您的合同有ensures条款,那么您很可能需要loop invariant,对于正在分析的代码中的每个单一循环来说都是如此。

更新 有了您提供的代码,邮资-C硅,不与frama-c -wp file.c证明的唯一事情就是在InitializeResetB循环不变。没有证明的原因是它是错误的。真正的不变量应为\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; 
} 
} 
+0

谢谢。请看我上面的最新评论。 – Rocolife

+0

谓词已经是\ forall。在初始化的循环不变中,如何在谓词之前使用另一个\ forall? – Rocolife

+0

对不起,您是对的。你建议的不变量是两个嵌套的“for”循环。这正是我们完成验证所需要的。非常感谢。 – Rocolife