static-analysis - ACSL "assigns"C 代码内部结构和字段的注释

标签 static-analysis frama-c acsl

假设我们有这样一个数据结构:

#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 的约定。如何为初始化合约编写正确的“分配”?

最佳答案

假设您正在使用插件 WP(请参阅上面的评论),您的主要问题是您还没有编写 loop assigns对于 Initialize 中的循环功能。 loop assigns对于您想要使用 WP 的函数中出现的每个循环都是必需的。另外,如果您的契约(Contract)有ensures条款,您很可能需要 loop invariant ,再次针对正在分析的代码中的每个循环。

更新 使用您提供的代码和 frama-c Silicon,唯一没有用 frama-c -wp file.c 证明的东西是 Initialize 中的循环不变式关于ResetB 。之所以没有被证明,是因为它是错误的。真正的不变量应该是 \forall integer i; 0<=i<Index ==> ResetB(&(Arg->A_Array[i])) 。通过以下完整示例,所有内容都会被放电,至少对于硅来说是这样:

#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;
 }
}

关于static-analysis - ACSL "assigns"C 代码内部结构和字段的注释,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43648733/

相关文章:

ios - 来自静态分析器的 API 滥用错误

code-analysis - 是否存在可自动查找复制和粘贴代码的工具?

swift - 是否可以在 Swift 中创建 "Positive Number"类型?

static-analysis - 定义硬件 "storage"以供 Frama-C EVA 处理

c - 为什么 Frama-C v20.0 Calcium 不支持在非全局范围内重新定义 typedef

c - 您如何告诉 Frama-C 和 Eva 入口点的参数被假定为有效?

c - Frama-C 用 "/*@ ensures"证明 While 循环

javascript - Flow.js 从节点模块推断返回类型

static-analysis - 是否可以在frama-c值分析器中注入(inject)值?

c - ACSL - 无法证明功能