文章目录
1. Motivation
CHA存在不精确的问题。对于下面的例子,n的声明类型为Number,使用CHA分析,那么n.get()会返回三个目标函数,分别是Zero.get One.get Two.get,这就导致x的接收了0 1 2三个不同的值,x最终为非常量NAC。但实际上我们期望调用One.get,得到返回值1。
因此引入指针分析,使n指向new One,解决这种CHA引入了很多假的调用边的问题。
2. Introduction to Pointer Analysis
指针分析是基础的静态分析,明确了程序中的指针可以指向哪些内存的地址,计算一个指针(variable或filed)可以指向哪些对象。
指针分析是一个may- analysis,是过近似的over-approximation
指针分析Pointer analysis:程序中的指针会指向哪些对象?
别名分析Alias analysis:两个指针可以指向同一个对象吗?
3. Key Factors of Pointer Analysis
影响指针分析精度和效率的因素有一下四种,这四个因素分别回答了对应的问题。
这里主要介绍红色部分
3.1 Heap Abstraction
在动态执行中,由于循环结构的存在,堆对象的数量是无限的。因此,在静态分析时,堆抽象Heap Abstraction把具体的对象抽象成有穷的抽象对象(把同类对象合并 )。
堆抽象主要分两大流派:Store based model和Storeless model,这里主要介绍Store based model中的Allocation sites
Allocation sites创建点:是堆抽象中最常用的技术。它指的是把在同一个创建点创建的对象都归为一类。即程序中有几个new语句,就有几个对象,这种方法抽象出来的对象肯定是有限的,因为程序是有限的。下面对象的下标表示代码行数
3.2 Context Sensitivity
上下文敏感:更精确。每一个函数在被调用的时候,考虑被调用时的上下文。为每一个调用点都创建一个上下文
上下文不敏感:不同的调用点使用同一个上下文,每一个函数只分析一次
下面的例子,左侧为上下文敏感的结果,右侧为上下文不敏感的结果
3.3 Flow sensitivity
流敏感Flow sensitivity:更精确,开销大。考虑语句的执行允许
流不敏感Flow insensitivity:忽略控制流的顺序,把程序当作一堆语句的无序集合。下面的例子中流不敏感存在误报
下面的例子,左侧为流敏感的结果,右侧为流不敏感的结果
3.4 Analysis scope
Analysis scope:明确了在做指针分析时,应分析程序中的哪些部分。
Whole-program:分析程序中所有指针的指向关系,分析一次可以获得所有的指向关系
Demand-driven:根据特定需求,只分析需求的指针分析,适用于有特定需求的指针分析
下面的例子,左侧为Whole-program的结果,右侧为Demand-driven(只考虑第五行)的结果
4. Concerned Statements
指针分析只关注影响指针的语句pointer-affecting statements
java当中的指针:
- Local variable: x。
- Static field: C.f。很多文献称其为global variable,类似于Local variable的处理
- Instance field: x.f。把它建模成一个对象(pointed by x)携带一个域 f
- Array element: array[i]。静态分析忽略下标,把数组建模成只有一个filed的对象,并把这个filed称为arr,此时它的处理类似于Instance field。
指针分析中关心的五种语句pointer-affecting statements:(对于复杂的a.b.c.d引入临时变量分解成三地址码)
其中前四种较为简单,不涉及方法调用。
第四种涉及到方法调用,这里关注最复杂的Virtual call