为什么Frama-C使用scanf()的程序的依赖关系图是这样的?

为什么Frama-C使用scanf()的程序的依赖关系图是这样的?,c,static-analysis,frama-c,C,Static Analysis,Frama C,我使用Frama-C工具生成这个程序的依赖关系图(main.C) 结果是 我的问题是为什么stations“m=m*i;”,“m=m%10000”不映射到节点。结果似乎不正确,因为代码中有三个循环。C程序的切片器只有在其定义目标为 要保留已定义的执行,允许切片器更改未定义的执行 否则,切片器将无法删除诸如x=*p一旦无法确定p在该点是有效指针,即使它知道它不需要x,仅仅因为如果删除该语句,p在该点为NULL的执行就会改变 Frama-C不处理复杂的库函数,例如scanf()。因此,它认为使用局部

我使用Frama-C工具生成这个程序的依赖关系图(main.C)

结果是
我的问题是为什么stations“m=m*i;”,“m=m%10000”不映射到节点。结果似乎不正确,因为代码中有三个循环。

C程序的切片器只有在其定义目标为 要保留已定义的执行,允许切片器更改未定义的执行

否则,切片器将无法删除诸如
x=*p
一旦无法确定
p
在该点是有效指针,即使它知道它不需要
x
,仅仅因为如果删除该语句,
p
在该点为NULL的执行就会改变

Frama-C不处理复杂的库函数,例如
scanf()
。因此,它认为使用局部变量
n
时没有初始化

类型
frama-c-val main.c
您应该得到如下警告:

main.c:10:[kernel] warning: accessing uninitialized left-value:
               assert \initialized(&n);
...
[value] Values for function main:
      NON TERMINATING FUNCTION
单词
assert
表示Frama-C的选项
-val
无法确定所有执行都已定义,“非终止函数”表示无法找到要继续执行的程序的单个已定义执行

未定义使用未初始化变量是PDG删除大多数语句的原因。PDG算法认为它可以删除它们,因为它们发生在它认为是未定义的行为之后,即第一次访问变量
n

我稍微修改了您的程序,用更简单的语句替换了
scanf()
调用:

#define EOF (-1)
int unknown_int();

int scan_unknown_int(int *p)
{
  *p = unknown_int();
  return unknown_int();
}

int main()
{
  int n,i,m,j;
  while(scan_unknown_int(&n) != EOF)
    { 
      m=n;
      for(i=n-1;i>=1;i--)
      {   
        m=m*i;
        while(m%10==0)
        {
          m=m/10;
        }
        m=m%10000;
      }  
      m=m%10;
      printf("%5d -> %d\n",n,m);
    }
  return 0;
}
我得到了下面的PDG。据我所知,它看起来很完整。如果您知道比
dot
更好的布局程序,但接受
dot
格式,这是使用它们的好机会

请注意,最外面的
状态变为
tmp!=-1
。图的节点是程序内部规范化表示的语句。条件
tmp!=-1对语句的节点具有数据依赖关系
tmp=unknown_int()。您可以使用
frama-c-print main.c
显示内部表示,它将显示最外面的循环条件已被分解为:

  while (1) {
    int tmp;
    tmp = scan_unknown_int(& n);
    if (! (tmp != -1)) { break; }
除其他外,这有助于切片仅删除复杂语句中可以删除的部分,而不必保留整个复杂语句

#define EOF (-1)
int unknown_int();

int scan_unknown_int(int *p)
{
  *p = unknown_int();
  return unknown_int();
}

int main()
{
  int n,i,m,j;
  while(scan_unknown_int(&n) != EOF)
    { 
      m=n;
      for(i=n-1;i>=1;i--)
      {   
        m=m*i;
        while(m%10==0)
        {
          m=m/10;
        }
        m=m%10000;
      }  
      m=m%10;
      printf("%5d -> %d\n",n,m);
    }
  return 0;
}
  while (1) {
    int tmp;
    tmp = scan_unknown_int(& n);
    if (! (tmp != -1)) { break; }