2

让我从这个例子开始我的问题:

void A (void)
{
  B();
  C();
  D();
  E();
  ... // function calls go on.

  return;
}

现在让我们在代码中添加 ACSL 注释:

/*@
   ensures PostConditionOfB();
   ensures PostConditionOfC();
   ensures PostConditionOfD();
   ensures PostConditionOfE();
   ... // ensuring the predicates of the remaining functions goes on.
*/
void A (void)
{
  B();
  C();
  D();
  E();
  ... // function calls go on.

  return;
}

我让 Frama-C 通过执行“frama-c-gui -wp file.c”来检查代码。在函数 A 中调用函数 B、C 和 D 时,合约标记为有效。通过添加函数 E 和可能更多其他函数的调用,合约被标记为无效。我们提出了在每个函数调用之后立即添加“断言”的想法,以便为 Frama-C 提供假设满足哪些后置条件的线索。通过这种方法,合同被标记为有效。查看代码:

/*@
   ensures PostConditionOfB();
   ensures PostConditionOfC();
   ensures PostConditionOfD();
   ensures PostConditionOfE();
   ... // ensuring the predicates of the remaining functions goes on.
*/
void A (void)
{
  B();
  //@ assert PostConditionOfB();
  C();
  //@ assert PostConditionOfB();
  //@ assert PostConditionOfC();
  D();
  //@ assert PostConditionOfB();
  //@ assert PostConditionOfC();
  //@ assert PostConditionOfD();
  E();
  //@ assert PostConditionOfB();
  //@ assert PostConditionOfC();
  //@ assert PostConditionOfD();
  //@ assert PostConditionOfE();
  ... // function calls go on.

  return;
} 

问题来了:有没有更好的方法来检查包含多个函数调用的函数的合同,而不是在每个函数调用之后立即添加“断言”?

更新代码:

file.h 如下所示:

#define SIZE_FIRST 100
#define SIZE_SECOND 30
#define SIZE_THIRD 30

typedef struct
{
int  Field_5;
int  Field_6;
} Struct_C;

typedef struct
{
int Field_1;
int Field_2;
int Field_3;
int Field_4;
Struct_C At_1 [ SIZE_SECOND ];
Struct_C At_2 [ SIZE_THIRD ];
Struct_C At_3 [ SIZE_THIRD ];
} Struct_B;

typedef struct
{
 Struct_B At [ SIZE_FIRST ];
 int Count;
} Struct_A;

/*@ predicate
  Reset_Basics (Struct_B * Stct_B) =
   (Stct_B->Field_1 == 0) &&
   (Stct_B->Field_2 == 0) &&
   (Stct_B->Field_3 == 0) &&
   (Stct_B->Field_4 == 0);
*/

/*@ predicate 
  Reset_At_1 (Struct_B * Stct_B, integer First, integer Last) =
    \forall integer Index; First <= Index < Last ==>
                (Stct_B->At_1 [ Index ].Field_5 == 0) &&
                (Stct_B->At_1 [ Index ].Field_6 == 0);
*/


/*@ predicate 
  Reset_At_2 (Struct_B * Stct_B, integer First, integer Last) =
    \forall integer Index; First <= Index < Last ==>
                (Stct_B->At_2 [ Index ].Field_5 == 0) &&
                (Stct_B->At_2 [ Index ].Field_6 == 0);
*/

/*@ predicate 
  Reset_At_3 (Struct_B * Stct_B, integer First, integer Last) =
    \forall integer Index; First <= Index < Last ==>
                (Stct_B->At_3 [ Index ].Field_5 == 0) &&
                (Stct_B->At_3 [ Index ].Field_6 == 0);
*/

file.c 如下所示:

#include "file.h"

void Initialize (Struct_A * const Stct_A);
void Reset (Struct_B * const Stct_B);
void Reset_Basics (Struct_B * const Stct_B);
void Reset_At_1 (Struct_B * const Stct_B);
void Reset_At_2 (Struct_B * const Stct_B);
void Reset_At_3 (Struct_B * const Stct_B);

/*@ 
   assigns Stct_A->At [ 0..(SIZE_FIRST - 1) ];
   assigns Stct_A->Count;
*/
void Initialize (Struct_A * const Stct_A)
{

/*@
 loop invariant 0 <= Index <= SIZE_FIRST;

 loop invariant \forall integer Stct_B_Index; (0 <= Stct_B_Index < 
      Index) ==> Reset_Basics(&(Stct_A->At [ Stct_B_Index ]));

 loop invariant \forall integer Stct_B_Index; (0 <= Stct_B_Index < 
      Index) ==> Reset_At_1(&(Stct_A->At [ Stct_B_Index ]), 0,   
      SIZE_SECOND);

 loop invariant \forall integer Stct_B_Index; (0 <= Stct_B_Index < 
      Index) ==> Reset_At_2(&(Stct_A->At [ Stct_B_Index ]), 0, 
      SIZE_THIRD);

 loop invariant \forall integer Stct_B_Index; (0 <= Stct_B_Index < 
      Index) ==> Reset_At_3(&(Stct_A->At [ Stct_B_Index ]), 0,
      SIZE_THIRD);

 loop assigns Index, Stct_A->At [ 0..(SIZE_FIRST - 1) ];

 loop variant SIZE_FIRST - Index;
*/
 for (int Index = 0; Index < SIZE_FIRST; ++(Index))
  {
   Reset(&(Stct_A->At [ Index ]));
  } 

  Stct_A->Count = 0;

 return;
 }

/*@ 
  assigns * Stct_B;
  ensures Reset_Basics(Stct_B);
*/
void Reset_Basics (Struct_B * const Stct_B) 
{

  Stct_B->Field_1 = 0;
  Stct_B->Field_2 = 0;
  Stct_B->Field_3 = 0;
  Stct_B->Field_4 = 0;

  return; 
}

/*@
  assigns Stct_B->At_1 [ 0..(SIZE_SECOND - 1) ];
  ensures Reset_At_1(Stct_B, 0, SIZE_SECOND);
*/
void Reset_At_1 (Struct_B * const Stct_B)
{
 /*@
 loop invariant 0 <= Index <= SIZE_SECOND;

 loop invariant Reset_At_1(Stct_B, 0, Index);

 loop assigns Index, Stct_B->At_1 [ 0..(SIZE_SECOND - 1) ];

 loop variant SIZE_SECOND - Index;
*/
  for (int Index = 0; Index < SIZE_SECOND; ++(Index))
  {
    Stct_B->At_1 [ Index ].Field_5 = 0;
    Stct_B->At_1 [ Index ].Field_6 = 0;
  }

  return;
 }

/*@ 
  assigns Stct_B->At_2 [0..(SIZE_THIRD - 1)];
  ensures Reset_At_2(Stct_B, 0, SIZE_THIRD);
*/
void Reset_At_2 (Struct_B * Stct_B)
{

 /*@ 
   loop invariant 0 <= Index <= SIZE_THIRD;

   loop invariant Reset_At_2(Stct_B, 0, Index);

   loop assigns Index, Stct_B->At_2 [0..(SIZE_THIRD - 1)];

   loop variant SIZE_THIRD - Index; 
 */ 
  for (int Index = 0; Index < SIZE_THIRD; ++(Index))
   {
     Stct_B->At_2 [ Index ].Field_5 = 0;
     Stct_B->At_2 [ Index ].Field_6 = 0;
   }  

    return;
 }


/*@ 
   assigns Stct_B->At_3 [0..(SIZE_THIRD - 1)];
   ensures Reset_At_3(Stct_B, 0, SIZE_THIRD);
*/
void Reset_At_3 (Struct_B * Stct_B)
{

  /*@ 
   loop invariant 0 <= Index <= SIZE_THIRD;

   loop invariant Reset_At_3(Stct_B, 0, Index);

   loop assigns Index, Stct_B->At_3 [0..(SIZE_THIRD - 1)];

   loop variant SIZE_THIRD - Index; 
   */ 
  for (int Index = 0; Index < SIZE_THIRD; ++(Index))
   {
     Stct_B->At_3 [ Index ].Field_5 = 0;
     Stct_B->At_3 [ Index ].Field_6 = 0;
   }  

  return;
 }

/*@ 
  assigns * Stct_B;
  ensures Reset_Basics(Stct_B);
  ensures Reset_At_1(Stct_B, 0, SIZE_SECOND);
  ensures Reset_At_2(Stct_B, 0, SIZE_THIRD);
  ensures Reset_At_3(Stct_B, 0, SIZE_THIRD);
*/

void Reset (Struct_B * const Stct_B)
{
   Reset_Basics(Stct_B);
   Reset_At_1(Stct_B);
   Reset_At_2(Stct_B);
   Reset_At_3(Stct_B);

  return;
}
4

0 回答 0