Point-to Analysis指针分析(1)_音程的博客-CSDN博客
前言
指针分析是一个非常复杂的工作,这些工作很多方向,比如是否是上下文敏感分析或上下文不敏感分析,显然,这难易度是不一样地。比如下图。对于同一段代码,敏感性分析如蓝色,不敏感分析如红色。
相比之下,不敏感分析不在乎语句的顺序,比如2,4两个语句换一下位置,得到的结果还是一样的,同时也不要求结果是否精确。
不敏感分析特点:安全。
即确保召回那个唯一正确的值就好,而不管精确不精确,是不是多了。
下面我们要讨论的就是不敏感分析。所以有些语句我们是不会管的,比如:
即,我们只管那些赋值的,和指针相关的语句。从而将此工作得到了大大简化。
Anderson’s pointer analysis
这个指针分析的算法很有名,是分析C语言的,但是思想都是通用的,下面开始介绍。
基础
解释:我们暂时先不看第一列和第三列,其他的应该很好理解。
- loc(b)表示b的地址。
- pts(a):point-to sets(a),表示a的可能指向集合,千万注意是可能指向,别忘了我们是做不敏感分析。即如果
a=&b,a=&c
,那么有pts(a)={loc(b),loc(c)}
。 - ∈,⊇,这个和数学中集合的概念一致,就是属于和子集关系的意思。
- 以第2行为例,有pts(a) ⊇ ptrs(b),为什么?举个例子你就明白了,如果有:a=&d,b=&c,a=b。那么pts(b)={loc(c)},pts(a)={loc(c),loc(d)}。所以明白了为什么pts(a)可能比pts(b)集合更大了吧,因为a=b把b的指向全部给了a,但是a可能还有其他的指向啊!
约束图
现在我们要做一些前期工作,并且要开始看上面那个表的第一列和第三列。举例来说,如果有代码:
p = &a;
q = &b;
*p = q;
r = &c;
s = p;
t = *p;
*s = r;
我们按照上面表的第3列翻译成下面,叫做约束:
p ⊇ {a}, q ⊇ {b}, *p ⊇ q, r ⊇ {c}, s ⊇ p, t ⊇ *p, *s ⊇ r
我们可以开始根据上面的表格创建初始约束图,其中基本(base)约束和(simple)约束是创建初始约束图的基础。初始约束图的创建分为如下三步:
- 首先为程序中的每个变量建立一个节点
- 后根据基本(base)约束标注节点的指向集
- 每一个初始的简单约束(simple)建立一条有向边
可以得到如下图:
解释:正如名字,上面只是约束图,而且只是一个初始约束图,图中的边也并不是指针的指向关系,而是约束关系。拿上图的边edge(p,s)为例,其表示p所指向的,s都将指向。
实战
下面用一个例子来进行实战整个Anderson算法。
int i, j, k;
int *a = &i;
int *b = &k;
a = &j;
int *p = &a;
int *q = &b;
p = q;
int *c = *q;
可以得到如下的约束:
a ⊇ {i, j}, b ⊇ {k}, p ⊇ {a}, q ⊇ {b}, p ⊇ q, c ⊇ *q
从而得到如下初始约束图:
上面的work_queue工作队列就是下面伪代码中的W。伪代码如下:
(我们已经完成了1,2步了)。
开始执行循环,从队列中取出a。
由于找不到关于a的复杂约束,复杂约束是什么?除了简单约束和基本约束就是复杂约束,具体可以参照开头的那个表格。
由于找不到a出发的边,所以此循环结束,如下。
取出b,
找不到关于b的复杂约束
找不到b出发的边
此循环结束,如下。
取出p,
找不到复杂约束
找不到p出发的边。
此循环结束,如下。
取出q,
找到复杂约束,c ⊇ *q
。q的指向有b,从而加入边edge(b,c)。而且加入b到工作队列中。
找到q出发的边edge(q,p),所以pts§={a,b},由于pts§改变了,增加了一个元素,所以p再次加入到工作队列中。
此循环结束。
取出b,
没有复杂约束
找到b出发的边,所以pts©={k},由于pts©改变了,所以c加入到工作队列中。
此循环结束。
取出p,
没有复杂约束
没有从p出发的边
此循环结束。
取出c,
找到复杂约束c ⊇ *q
,但是复杂约束的形式和算法中的不一样,所以for循环结束。
找不到c出发的边
此循环结束。
由于工作队列为空,此算法结束。
将旁边的那些集合比如{i,j}统统连上,即edge(a,i),edge(a,j)…。就变成了我们最终要的指针指向关系了。
这样我们就完成了指针分析。