在ACSL后置条件下\ old的含义

时间:2012-03-29 19:01:01

标签: design-by-contract formal-verification frama-c

我是Frama-C的新手用户,并且有一些关于断言的问题 指针。

考虑下面涉及的C片段:

  • 两个相关的数据结构Data and Handle,s.t。句柄有一个指向数据的指针;
  • 数据中的“州”字段,表示某些假设操作是否已完成
  • 三个函数:init(),start_operation()和wait();
  • 使用上述的main()函数,包含6个断言(A1-A6)

现在,为什么使用WP验证程序(“frama-c -wp file.c”)无法声明A5和A6 由于start_operation()上的最后一个“ensure”子句,它们不应该成立吗?

我做错了什么?

最佳,

爱德华多

typedef enum 
{ 
  PENDING, NOT_PENDING
} DataState;

typedef struct 
{
  DataState state;
  int value;  
} Data;


typedef struct 
{
  Data* data;
  int id;
} Handle;

/*@
  @ ensures \valid(\result);
  @ ensures \result->state == NOT_PENDING;
  @*/
Data* init(void);

/*@ 
  @ requires data->state == NOT_PENDING;
  @ ensures data->state == PENDING;
  @ ensures \result->data == data;
  @*/  
 Handle* start_operation(Data* data, int to);

/*@
  @ requires handle->data->state == PENDING;
  @ ensures handle->data->state == NOT_PENDING;
  @ ensures handle->data == \old(handle)->data;
  @*/  
 void wait(Handle* handle);


 int main(int argc, char** argv)
 {
  Data* data = init();
  /*@ assert A1: data->state == NOT_PENDING; */

  Handle* h = start_operation(data,0);
  /*@ assert A2: data->state == PENDING; */
  /*@ assert A3: h->data == data; */

  wait(h);
  /*@ assert A4: h->data->state == NOT_PENDING; */
  /*@ assert A5: data->state == NOT_PENDING; */
  /*@ assert A6: h->data == data; */

  return 0; 
}

1 个答案:

答案 0 :(得分:2)

你正在为“新手”验证一些棘手的记忆操作。

ACSL构造\old的效果与您认为的完全不同。

首先,后置条件中的\old(handle)handle相同,因为handle是参数。合同旨在从呼叫者的角度使用。即使函数wait修改了handle(这可能是不寻常的但是可能的),它的契约仍然打算将调用者作为参数传递的值与函数返回给调用者的状态相关联。

简而言之,在ACSL后置条件中parameter始终意味着\old(parameter) (即使该函数像本地变量一样修改parameter)。< / p>

其次,上述规则仅适用于参数。对于全局变量和内存访问,后置条件被认为适用于后置状态,正如您对其名称所期望的那样。您编写的构造\old(handle)->data,相当于handle->data,意味着“句柄的旧值指向新状态的字段.data”,以便后条件handle->data == \old(handle)->data是一个重言式,可能不是你想要的。

从上下文来看,您似乎打算使用handle->data == \old(handle->data),这意味着“.data的旧值在新状态中指向的字段handle等于该字段.data旧值handle指向旧状态的{{1}}。通过该更改,程序中的所有断言都会得到证实(使用Alt-Ergo 0.93)。