数据流分析的局限性

#引子
前面我们介绍了很多关于数据流分析的知识,虽然说数据流分析是整个代码分析基础中的基础,但是数据流分析还是存在很大的局限性,一部分局限性来自于数据流分析所做的假设(例如假设所有路径可达),一部分局限性来自于分析语言的性质(例如C++语言中的异常处理或多态)。为了作出可靠的决定,所以编译器设计者必须了解数据流分析能做什么以及它不能做什么。

Nodes are required to hold information even when it is not directly related to the node, hence, each node must store complete in and out sets.

长久以来,很多不同的数据流问题已被公式化,如果每一个转换使用它自己特定的分析,那么花费在实现、调试和维护分析上的时间和精力就会变得很大。另外传统的数据流分析是一种dense的分析,就像上述英文描述的那样,即使当前program point与当前信息无关,也要携带者这些无关信息穿越该点。

  • dense分析:要用个容器携带所有变量的信息去遍历所有指令,即便某条指令不关心的变量信息也要携带过去。
  • sparse分析:变量的信息直接在def与use之间传播,中间不需要遍历其它不相关的指令。

注:上述关于 dense分析sparse分析的内容来自于知乎R大的回答,详见过程间和过程内的数据流分析算法在类似LLVM的IR或HotSpot C1的HIR中,是如何实现的? 希望R大不要见怪

那么有没有其他的技术能够缓解此问题呢,静态单态赋值就是(static single assignment, SSA)就是这样一种技术,后面我们会介绍该技术。在这篇文章中我们先分析一下数据流分析的局限性。


##数据流分析中的假设
当我们沿着控制流图(CFG)做数据流分析时,我们的控制流方程是无条件的进行交汇运算的,例如到达定值中的控制流方程,会合并当前基本块的所有前驱基本块出口的数据流值,而不做任何可靠的推断。当然为了保证安全性,考虑所有可能的路径是必要的。因为数据流分析得到的信息是用来改进代码行为,所以如果数据流信息是错误的,那么改进后的程序也会改变原有的语义。

所有的数据流分析假设CFG上的所有路径都可达,所以数据流分析得到的数据流值总是会附带上一定得不确定性。这是数据流分析的本质所决定的,数据流分析毕竟是路径无关的,如果想要获得动态的信息,像KLEE那样,直接把IR放在虚拟机上边跑边符号执行得了,但是那就脱离符号执行的原意了。


##数据流分析中的指针
信息的非精确性另一部分是来自于对 数组指针过程间调用 的处理,例如在取A[i]的时候,如果不能确切知道i的值,只能假设所有A的元素都被引用到了。指针会给静态分析带来另外一层不确定性,并且指针的运算会把问题搞得更复杂。如果编译器没有指针分析的话,编译器必须把对指针变量所指向位置的赋值,解释为该指针所能指向的所有变量的赋值 。虽然类型系统可以把这些可能变量的集合缩小,但是在C语言这种类型不安全的语言中,指针有可能指向任何类型,所以在C语言中这个问题更加复杂。

另外过程调用也会导致数据流分析的不精确,例如C语言中的函数指针以及C++中的动态指派(虚函数),都会在数据流分析的时候无从建立调用过程和被调用过程之间的关系。所以在数据流分析的时候只能假设,调用函数可能会修改所有全局变量,可能会修改指针参数指向的任何变量。这进一步的增加了数据流分析的不精确性。数据流分析保守,为了保证安全性,只能保持着这种不精确性了。

你可能感兴趣的:(编译)