我们首先专注于过程内分析,将对函数调用的处理推迟到第11.4节。
必须获取的最重要信息是指针可能指向的内存单元集合。在执行期间,可能存在任意多个可能的单元,因此我们必须选择一些有限的抽象。一种常见的选择,称为分配点抽象(allocation-site abstraction)[CWZ90],是为
每个抽象单元表示在相应源位置分配的运行时单元集合,因此称为分配点抽象。对于给定的程序,我们用Cells表示抽象单元的集合。
我们将要研究的第一类分析是流不敏感的。这种分析的最终结果是一个函数 $pt: Vars \\rightarrow \\mathcal{P}(Cells)$,对于每个指针变量X,它返回抽象单元集合pt(X),表示X可能指向的抽象单元的集合。这类分析被称为指向分析(points-to analysis)。我们希望进行一种保守的分析,计算出的集合可能会过大,但永远不会过小。
有了这样的指向信息,可以近似许多其他事实。如果我们想知道指针变量 x 和 y 是否可能是别名,那么通过检查 $pt(x) \\cap pt(y)$ 是否非空来得到一个安全的答案。
在TIP程序中,局部变量的初始值是未定义的。然而,对于这些无流敏感的指向分析,我们假设所有变量在使用之前都被初始化。换句话说,这些分析仅对从未读取未初始化变量的程序有效(参见第5.9节)。
一个几乎平凡的分析,称为地址取值(address taken),是简单地返回所有可能的抽象单元;除非在给定程序中出现表达式 &X,那么就只包括变量X(因为这就是直接的取地址,所以这个指针一定指向当前的X)。这仅足够用于非常简单的应用程序,因此通常会选择更雄心勃勃的方法。如果我们将自己限制在可类型化的程序上,那么任何指向分析都可以通过移除那些类型与指针变量的类型不匹配的单元来进行改进。