指向数组的指针断言

时间:2017-09-06 09:21:46

标签: frama-c

我定义了以下函数,frama-c证明了这一点:

//ensures array <= \result < array+length && *\result == element;
/*@
  requires 0 < length;
  requires \valid_read(array + (0 .. length-1));

  assigns  \nothing;

  behavior in:
    assumes \exists int off ; 0 <= off < length && array[off] == element;
    ensures *\result == element;

  behavior notin:
    assumes \forall int off ; 0 <= off < length ==> array[off] != element;
    ensures \result == 0;

  disjoint behaviors;
  complete behaviors;
*/
int* search(int* array, int length, int element){
   int *tmp;
  /*@
    loop invariant 0 <= i <= length;
    loop invariant \forall int j; 0 <= j < i ==> array[j] != element;
    loop assigns i;
    loop variant length-i;
  */ 
  for(int i = 0; i < length; i++)
  {
    if(array[i] == element) 
    {
        tmp = &array[i];
        //@ assert *tmp==element;
    }
    else
    {
        tmp = 0;    
    }
  }
  return tmp;
}

我在以下主条目中使用它:

int main(){
  int arr[5]={1,2,3,4,5};
  int *p_arr;

  p_arr = search(arr,5,4);
  //@ assert *p_arr==30;

  return 0
}

我想知道为什么frama-c给出断言&#34; // @ assert * p_arr == 30;&#34;是的,我不明白。

由于

2 个答案:

答案 0 :(得分:0)

仅使用命令行,我在代码中看到了一些问题:

    循环分配中缺少
  • tmp;
  • 你需要:
    • break函数的then分支中添加seach (然后你会在第一个匹配的元素上返回指针)
    • 或在函数开头初始化tmp = 0并删除循环中的else分支(然后你会在最后一次出现时返回一个指针)。

我没有尝试使用GUI,但是你说你的例子是:

,这似乎很奇怪
  

很好地证明了frama-c

我建议您先使用命令行。

答案 1 :(得分:0)

好的,现在我更正了我的代码如下:

//ensures array <= \result < array+length && *\result == element;
/*@
  requires 0 < length;
  requires \valid_read(array + (0 .. length-1));

  assigns  \nothing;

  behavior in:
    assumes \exists int off ; 0 <= off < length && array[off] == element;
    ensures *\result == element;

  behavior notin:
    assumes \forall int off ; 0 <= off < length ==> array[off] != element;
    ensures \result == 0;

  disjoint behaviors;
  complete behaviors;
*/
int* search(int* array, int length, int element){

  /*@
    loop invariant 0 <= i <= length;
    loop invariant \forall int j; 0 <= j < i ==> array[j] != element;
    loop assigns i;
    loop variant length-i;
  */ 
  for(int i = 0; i < length ; i++)
  {
    if(array[i] == element) 
    {
        return &array[i];
    }
  }
  return 0;
}

并添加以下断言:

int main()
{
    int arr[5] = {1,2,3,4,5};
    int *ptr;

    ptr = search(arr,5,3);
    //@ assert *ptr==3;

}

然后运行:frama -c -wp -rte myfile.c并得到结果:

[wp] Proved goals:   65 / 65
     Qed:            35  (1.00ms-6ms-24ms)
     Alt-Ergo:       30  (16ms-30ms-94ms) (132)

如果我设置另一个断言:

int main()
    {
        int arr[5] = {1,2,3,4,5};
        int *ptr;

        ptr = search(arr,5,3);
        //@ assert *ptr==5;

    }

然后我得到输出:

[wp] [Alt-Ergo] Goal typed_main_assert_2 : Timeout (Qed:4ms) (10s)
[wp] Proved goals:   64 / 65
     Qed:            35  (1.00ms-4ms-10ms)
     Alt-Ergo:       29  (16ms-28ms-109ms) (132) (interrupted: 1)

所以断言是“未知”,正如我们所料,如果我们运行frama-c-gui,子弹是橙色的。

这样工作正常,请注意错误的公理事物! 谢谢安妮的帮助。