使用ACSL / Frama-C介绍数学函数规范

时间:2014-06-24 15:29:55

标签: static-analysis frama-c

是否可以在ACSL中实现通常在使用-lm编译时调用的函数的规范,如sqrt?我将它用于Frama-C的插件WP。

这是一个小例子来说明我想要做的事情。

/*@ requires sqrt_spec: \forall float x; 
             \model(sqrt(x)) * \model(sqrt(x)) == \model(x);  
    ensures [...] */  

void f (...) {
double y = sqrt x;
[...]
}

显然,如果我这样做,WP会哭,因为当我在注释中使用它时,sqrt不存在。

  

[kernel]用户错误:注释中的未绑定函数sqrt

所以我想定义一个抽象的sqrt,但我的测试都没有工作:

#define sqrt(x) (...)

对于这个我没有看到我可以放入(...)因为我想要一个抽象定义而不是重新实现整个浮动sqrt。

/*@  axiomatic SqrtSpec {
logic real sqrt (real x);
} */

这个并不能解决我的问题:

  

函数sqrt的代码和规范都没有,从原型生成默认赋值。

1 个答案:

答案 0 :(得分:4)

Frama-C有一个内置逻辑函数\sqrt,可以在real个数字上运行(请注意,内置函数和谓词通常以反斜杠\为前缀,以避免任何与现有C标识符冲突)。也就是说,为sqrt提供公理定义并不困难:

axiomatic Sqrt {
  logic real sqrt(real);
  axiom real_def: \forall real x; x >= 0 ==> x == sqrt(x) * sqrt(x);
}

另外请注意,Gappa(http://gappa.gforge.inria.fr/)是关于浮点数(而不是实数)的唯一自动化证明者,但即使你已经安装了浮点数,也要解决浮点数的问题。计算可能非常困难。

<强>更新

如果你想要公理化double sqrt(double)(和/或float sqrt(float)),那么我们的想法就是将相对于\sqrt运算的结果的错误定义为实数,即类似于

axiomatic Sqrt {
  logic float sqrt(float sqrt);
  axiom sqrt_def: \forall float x; \is_finite(x) && x>= 0.0 ==> sqrt(x) ==  (float)\sqrt(x);
}

当然,这种表征可能有点限制。您可能想要\abs(sqrt(x) - \sqrt(x)) <= err_bound * \sqrt(x)这样的内容,但我必须承认,我在浮点计算方面不够流畅,无法从头脑中提供err_bound的适当值。

更新2

假设你有一个逻辑 sqrt具有你想要的属性,说 C sqrt具有相同的行为就是是给予合同的问题:

/*@ requires \is_finite(x); //unless you want to play with NaN or infinities 
    assigns \nothing;
    ensures \result == sqrt(x);
 */
extern float sqrt(float x);

在链接阶段合并函数的规范,因此无论此合同是否写在math.h中都是无关紧要的(NB:在标准头sqrt中取(并返回){ {1}},double可以在sqrtf}或您自己的文件中运行。