为什么这个scanf()的依赖图 - 使用Frama-C的程序看起来像这样?

时间:2012-03-25 12:12:10

标签: c static-analysis frama-c

我使用Frama-C工具生成该程序的依赖图(main.c)。

    #include<stdio.h>
    int main()
    {
        int n,i,m,j;
        while(scanf("%d",&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;
    }

命令是:

    frama-c -pdg -dot-pdg main main.c 
    dot -Tpdf main.main.dot -o main.pdf

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

1 个答案:

答案 0 :(得分:6)

C程序的切片器只有在定义目标时才能在实践中使用 保留已定义的执行,允许切片器更改未定义的执行

否则,只要x = *p;无法确定p是该点的有效指针,切片器就无法删除x等语句,即使它知道它确实存在不需要p,只是因为如果删除了该语句,则scanf()在该点为NULL的执行会发生变化。

Frama-C不处理复杂的库函数,例如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

单词-val表示Frama-C的选项n无法确定是否已定义所有执行,而“NON TERMINATING FUNCTION”表示无法找到单个已定义的执行程序继续。

未初始化变量的未定义使用是PDG删除大多数语句的原因。 PDG算法认为它可以删除它们,因为它们是在它认为是未定义的行为之后,第一次访问变量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; } 调用:

dot

我得到了以下的PDG。据我所知,它看起来很完整。如果您知道的布局程序比dot更好,但接受while格式,则很有可能使用它们。

Complex PDG 请注意,最外面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; } 显示内部表示,它将显示最外面的循环条件已被分解为:

{{1}}

除其他外,这有助于切除仅删除可以删除的复杂语句的部分,而不必保留整个复杂语句。