为什么迭代总数没有边缘导致无限或有限多次循环展开?

时间:2015-11-18 06:50:39

标签: c infinite-loop cbmc

#include<stdio.h>

#define N 6
#define M 10

typedef int bool;
#define true 1
#define false 0

unsigned int nondet_uint();  

typedef unsigned __CPROVER_bitvector[M] bitvector; 

unsigned int zeroTon(unsigned int n) {
   unsigned int result = nondet_uint();
   __CPROVER_assume(result >=0 && result <=n);
   return result ;
};


//Constrine the value between 0 and 1
unsigned int  nondet (){  
  unsigned int num = nondet_uint();
  __CPROVER_assume( num>= 0 && num  <= 1);
  return num;
}; 

void main() {
   unsigned int pos , i, j, k;

   unsigned int len = 0;
   bool Ch , Ck , C0 ;

  bitvector compartment1 , compartment2 , compartment3 , compartment4, compartment5, compartment6;
bitvector nodes[N] = {compartment1, compartment2, compartment3, compartment4, compartment5, compartment6};


// Represent the graph with given topology 
unsigned int graph[N][N];

for(i=0;i <N; i++) {
    for(j=0;j<N;j++) {
        graph[i][j] = nondet();
    }
}



unsigned int p[N] ;
unsigned int ticks;


   //Make sure that graph is one connected  : just find one hamiltonian cycle 
   //make sure elements are in between node no's and all are distinct

for(i=0; i<N; i++) {
    p[i] = zeroTon(5);
}

for(i=0; i <N; i++) {
     for(j=0; (j<N) && (j!=i) ; j++) {    
    if( p[i] != p[j]){
            C1 = C1 && 1;
        }
        else {
            C1 = C1 && 0;
        }

     }
}

 //hamiltonian One exists 
 for(i=0;i<N-1;i++) {
    if( graph[p[i]][p[i+1]] == 1) {
       Ch = Ch && 1;
    }
   else {
       Ch = Ch && 0;
   }
  }

 len =0;
 for(i=0;i<N;i++) {
   for(j=0;j<N; j++){
          if (graph[i][j] == 1) {
              len = len + 1;
          }
    }
  }

  //THIS IS GOING IN INFINITE LOOP ?? WHY ?? 
  for(i=0;i<len;i++) {
   printf("i'm a disco dancer ");

  }
  __CPROVER_assert(!(Ch && C1) , "Graph has an ham path");
}      

我只是试图获得具有汉密尔顿路径的总节点6的图形。这适用于上面的代码。但是当我尝试使用len即总数时,我会在cbmc run中获得无限的展开。

以上代码运行良好,除非我使用len迭代。 cbmc运行进入无限平仓?谁能解释一下。

1 个答案:

答案 0 :(得分:1)

我不确定堆栈溢出的政策,但为了澄清问题,我发布了牛津大学的Martin在CBMC支持论坛上发布的答案。

  

以上代码运行良好,除非我使用len迭代。 cbmc运行    进入无限循环?谁能解释一下。

     

简短回答:是的,预计会使用--unwind

     

答案很长:CBMC对循环边界的检测相对简单;它   只会停止展开循环(没有循环展开限制)   在符号期间,分支条件可以静态简化为false   执行。

     

因为图的值是非确定性的,所以len的值   将是不确定的。当然,我们从其余的方式知道   代码工作len&lt; = N * N但这不能通过   仅仅简化,因此CBMC没有意识到&#39;这个循环   放松不会自行终止。

     

为什么我们不让绑定检测变得更聪明?比如说,跟踪间隔   变量?除非你有完整的决策程序,否则我们可以   在那里,你总能找到这样的案例。如果你把一个完整的   决定程序在那里你要么做基于路径的象征   执行,这是我们的symex工具所做的,或者你正在做的事情   增量BMC(我们有可用的工具,它们可能合并   进入下一版CBMC),取决于你是否正在决定   单独或一起展开和断言。

感谢所有人的帮助。