如何找到循环的固定点,为什么我们需要它?

时间:2014-03-03 15:39:49

标签: testing static-analysis

我知道在程序的静态分析中,我们需要找到fixpoint来分析所提供的info循环。

我已经阅读了Secure_programming_with_Static_Analysis一书中的wiki以及相关的材料。

但我仍然对概念修复点感到困惑,所以我的问题是:

  1. 任何人都可以给我一些关于这个概念的解释吗,

  2. 在静态分析中找到固定点的实用方法(方法)是什么?

  3. 找到修复点后我们可以获得哪些信息?

  4. 谢谢!

1 个答案:

答案 0 :(得分:3)

从概念上讲,通过在一组抽象值上重复迭代,fixpoint对应于您获得的关于循环的最多信息。我将通过“静态分析”来猜测你在这里指的是“数据流分析”或最接近数据流分析的“抽象解释”版本:使用可能程序的抽象模拟程序执行在每个点上陈述。 (模型检查遵循双重直觉,因为您使用可能的执行路径的抽象来模拟程序状态。两者都是具体程序行为的近似。)

鉴于有关程序点的一些知识,这个“模拟”对应于我们知道特定程序构造必须对我们所知道的影响。例如,在程序的某个时刻,我们可能知道x可以(a)未初始化,或者从语句(b)x = 0或(c)x = f(5)获得其值,但在(d)x = 42之后,其价值只能来自(d)。另一方面,如果我们有

if ( foo() ) {
    x = 42;  // (d)
    bar();
} else {
    baz();
    x = x - 1; // (e)
}

之后x的值可能来自(d)或(e)。

现在想想循环会发生什么:

while ( x != 0 ) {
    if ( foo() ) {
        x = 42;  // (d)
        bar();
    } else {
        baz();
        x = x - 1; // (e)
    }
}

在输入时,我们可以从 {a,b,c} 中定义x。一次通过循环意味着可能的定义来自 {d,e} 。但是如果foo()最初失败会导致循环根本不运行会发生什么?那么x有什么可能性?好吧,在这种情况下,循环体没有效果,因此x的定义将来自 {a,b,c} 。但如果它运行,甚至一次,那么答案是 {d,e} 。所以我们在循环结束时知道关于x的是循环运行或不运行,这意味着x的赋值可以是任何一个或 {a,b,c,d,e} :这里唯一安全的答案是循环条目中已知属性的 union {a,b ,c} )并且在一次迭代结束时知道属性( {d,e} )。

但这也意味着我们必须将x {a,b,c,d,e} 关联到循环体的开头,因为我们无法确定这是第一次还是第四千次通过循环。所以我们必须再次考虑我们在循环退出时可以拥有的东西:循环体效果与假定在最后一次迭代时保持的属性的并集。令人高兴的是,这只是 {a,b,c,d,e}∪{d,e} = {a,b,c,d,e} 。换句话说,我们没有通过循环体的第二次模拟获得任何额外的信息,因此我们可以停止,因为没有进一步的模拟迭代会改变结果。

这是固定点:程序状态的抽象将导致模拟产生完全相同的结果。

现在关于找到它的方法,有很多,虽然最简单(“混乱的迭代”)只是运行每个程序点的模拟(根据一些公平的策略),直到答案没有改变。在大多数编译器教科书中都可以找到学习更好算法的良好起点,尽管通常不会在第一门课程中讲授。 Steven Muchnick的高级编译器设计和实现是一个更全面,更易读的主题处理方法。如果您能找到副本,Matthew Hecht的计算机程序流程分析是另一种经典的治疗方法。这两本书都侧重于静态分析的“数据流分析”技术。您也可以尝试Nielson / Nielson / Hankin的程序分析原理,尽管书中的技术细节可能非常多毛。另一方面,它提供了更为一般的静态分析处理。