【问题标题】:Understanding Frama-C slicer results了解 Frama-C 切片器结果
【发布时间】:2013-07-10 13:47:02
【问题描述】:

我想知道是否可以使用 Frama-C 进行某种前向条件切片,我正在通过一些示例来了解如何实现这一点。

我有这个简单的例子,它似乎导致了一个不精确的切片,我不明白为什么。这是我要切片的函数:

int f(int a){
int x;
if(a == 0)
    x = 0;
else if(a != 0)
    x = 1;
return x;
}

如果我使用这个规范:

/*@ requires a == 0;
  @ ensures \old(a) == a;
  @ ensures \result == 0;
*/

然后 Frama-C 使用“f -slice-return”标准和 f 作为入口点返回以下切片(精确):

/*@ ensures \result ≡ 0; */
int f(void){
  int x;
  x = 0;
  return x;
}

但是当使用这个规范时:

/*@ requires a != 0;
  @ ensures \old(a) == a;
  @ ensures \result == 1;
*/

然后所有指令(和注释)仍然存在(当我等待这个切片返回时:

/*@ ensures \result ≡ 1; */
int f(void){
  int x;
  x = 1;
 return x;
}

)

在最后一种情况下,切片是否不精确?在这种情况下,可能是什么原因?

问候,

罗曼

编辑:我写了“else if(a != 0) ...”,但问题仍然存在于“else ...”

【问题讨论】:

    标签: slice frama-c


    【解决方案1】:

    在 Frama-C 中,切片插件依赖于称为值分析的初步静态分析插件的结果。


    这个值分析可以表示变量aa == 0 的值(在这种情况下,值的集合是{ 0 })但是很难表示a 的值,因为已知a != 0。在后一种情况下,如果尚不知道a 是正数还是负数,则值分析插件需要近似a 的值集。如果已知a 为正数,例如如果它是unsigned int,则非零值可以表示为一个区间,但值分析插件不能表示“除0 之外的所有int 类型的值”。


    如果你愿意改变前置条件,你可以写成更容易被价值分析插件理解的形式(连同价值分析选项-slevel):

    $ cat t.c
    /*@ requires a < 0 || a > 0 ;
      @ ensures \old(a) == a;
      @ ensures \result == 0;
    */
    
    int f(int a){
    int x;
    if(a == 0)
        x = 0;
    else if(a != 0)
        x = 1;
    return x;
    }
    $ frama-c -slevel 10 t.c -main f -slice-return f -then-on 'Slicing export' -print 
    …
    /* Generated by Frama-C */
    /*@ ensures \result ≡ 0; */
    int f(void)
    {
      int x;
      x = 1;
      return x;
    }
    

    【讨论】:

    • 感谢您的回答(我顺便接受了它 - 抱歉,我不知道您必须这样做以及如何去做,新手发现 =))!我查看了价值分析手册,但我不明白为什么 -slevel 至少需要为 3(为什么不只是 2)?你能简单解释一下吗?
    • @roo 选项-slevel 为价值分析提供了叠加内存状态的许可,例如a &lt; 0 的一个内存状态和a &gt; 0 的另一个内存状态。结果是条件a != 0 毕竟已经用间隔“表示”了。但是您的函数还包含ifs,来自两个分支的状态,选项-slevel 也试图叠加。这可能是-slevel 2 不够用的原因。但是没有理由尝试为-slevel 使用正确的值,只要它足够精确并且不占用太多时间。因此,-slevel 10.
    【解决方案2】:

    这与您的主要问题无关,但您的 ensures a == \old(a) 子句没有达到您的预期。如果您使用选项-print 漂亮地打印您的源代码,您会看到它已被默默地转换为ensures \old(a) == \old(a)

    ACSL 语言不允许在 post-state 中引用形式变量的值,主要是因为从调用者的角度来看这是没有意义的。 (调用终止后弹出被调用者的栈帧。)

    【讨论】:

    • 感谢您的回答。有没有办法确保在执行过程中 a 的值不变?我想我可以使用强大的全局不变量来做到这一点,但我想我必须要么创建一个全局变量,要么使用另一个全局变量,但是否可以不修改当前代码?
    • 不是,不是。请注意,即使没有全局不变量,您当前的规范也可以使用全局变量。在这种情况下,规范化a -&gt; \old(a) 不会发生,因为它仅对形式参数执行。在调用期间修改形式参数对调用者来说是不可见的(在按值调用设置中),因此它在 ACSL 中是不可表达的。但是,您可以改为注释正文,并在 return 指令之前插入断言 a == \old(a)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多