指针分析/Point-to Analysis/Reference Analysis

原创 2015年11月21日 10:44:23

目录

指针分析

指针分析紧接数据流分析,是静态分析中的一个难点。遗憾的是能把相关内容讲得通俗易懂的资料非常少,中文的更基本没有。所以我斗胆在这里以例子的形式讲一下静态分析中的指针分析。参考资料主要在.
如果有讲错的地方还望斧正。


指针分析的目的

对于任何一个指针/引用,能否在编译阶段就知道它会指向内存那块位置(位置在这里并不是0xFFFF这样的具体位置,而是说指向哪个stack/heap上local/object)呢?
通过把停机问题reduced to, 能证明指针问题是不可决定的。也就是不能对任何指针都准确的分析出它会确切指向哪。但这不妨碍我们求出近似解,从而在某些情况下能作出优化。
因此我们把问题转化为: 对于任何一个任何指针,能否在编译阶段知道它所有可能(may)指向的位置?
最简单的回答自然是不知道(top), 这种回答没有实际意义,我们要的是更”紧”的答案。

基础

因为我们关心的是指针所指向的位置,指针是一个变量,能改变变量值的命令只有赋值语句。
和C类似,我们定义有关指针的赋值语句见下表第一列:

赋值 约束 意义
a = &b
ab
bpts(a)
a = b
ab
pts(a)pts(b)
ba
a = *b
ab
vpts(b)|pts(a)pts(v)
*a = b
ab
vpts(a)|pts(v)pts(a)

先回顾下C中指针操作符的意义。’&’是取地址符,’*’是取值符。对于整形,它的值是个32位的整数; 那么指针的值是什么? 在程序运行时它也是一个数字,只是这个数字代表的内存的某块地址。在这里我们不关系心这具体地址是什么(也没法关心),我们研究的指针变量指向的是谁的地址。”谁”具体可以分为stack内存上局部变量,也可以是位于heap上的对象,在这里我们不作区分,统一抽象成一个变量,用小写字母表示。注意指针它本身也是变量,以上地址描述同样适用于它,指针分析难点正来于此。

因此指针p实际是一个集合(pts),它的元素是所有它可能指向的变量。所以不难理解表中前两行的约束和意义了: 当把变量b所在的地址赋值给a时,a可能指向的变量自然就包含了b的地址啦; 当b是指针时,把b的值赋值给a相当于把b所有可能的元素添加到a中。对于’*’我们要多分析一层,*b表示的是b中的每个元素。举个例子, 假设b = {p, q},那么*b指的就是p和q啦。so对于第三行相当于把p的值赋值给a且把q的值赋值给a, 也就是把集合p和q的所有元素添加到a里。第四行则是把(假设a = {i, j}) b赋值给i且也赋值给j, 也就是i和j都讲拥有b所有的元素。

同其它数据流分析一样,在分析时我们先把赋值语句转化成约束,在对约束求解不动点从而得出每个指针变量的值。

在进入求解不动点算法讲解前,先提一下什么是flow-insensitive。flow指的是控制流,对它不敏感代表语句的排列顺序对我们分析结果没有影响。我在这里讲得是flow-insensitive的分析。

Anderson 算法

本质上是个非常简单又很常用的workqueue(worklist)算法,只要会写宽度优先都能轻松实现。我们把表中第一行的赋值语句称为base语句,第二行的称为simple语句, 其余的称为complex。
先贴出来算伪代码:

// 代表指针的数据结构
class Pointer {
    final String sid;
    Set<Pointer> pts;
}

Set<Pointer> nodes; // 存储了代码片中出现的所有的指针变量,每个变量代表一个约束图的结点
init(nodes); // 依据上节表中第四列规则初始化图的边; 并把base和simple的结点初始化
Queue<Pointer> workQueue = new LinkedList<>(); 
for (Pointer node : nodes) {
    if (!node.pts.isEmpty()) {
        workQueue.add(node);
    }
}
while (!workQueue.isEmpty()) {
    Pointer v = workQueue.remove();
    for (Pointer a : v.pts) {
        for (Constraint constraint : constraints) {
            if (constraint.rightOp.star.contains(v)) {
                Pointer p = constarint.leftOp;
                // 添加a->p的边,如果边是新的则添加a至wq
                if (addEdge(a, p)) {
                    workQueue.add(a);
                } 
            } else if (constraint.leftOp.star.contains(v)) {
                Pointer q = constraint.rightOp;
                if (addEdge(q, a) {
                    workQueue.add(q);
                }
            }
        }
    }
    for (Edge edge : edges) {
        if (edge.from.equals(v)) {
            Pointer q = edge.to;
            int size = q.pts.size();
            q.pts.addAll(v.pts); 
            if (q.pts.size() != size) {
                workQueue.add(q);
            }
        }
    }   
}

通过不断添加边和结点内集合的元素直到图不再改变为止。因为union操作是单调的,lattice的元素是集合,因此能证明一定能求出不动点使得图不再改变。

例子

实例代码片 包含的赋值语句:
Base
p = &a
q = &b
r = &c
Simple
s = p
Complex
*p = q
t = *p
*s = r

图示

这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述

时间复杂度

N个结点,最多有O(N2)条边。每条边被引入时最多引入O(N)连带反应(e.g. a->b->c->d…, abcd..依次入队列),每条边最多引入一次, 所以复杂度是O(N3).


指针的相关概念(简)

基本概念:         1、地址(c语言):C语言地址,是指内存地址的概念。计算机内存中的各个存储单元都是有序的,按字节编码。字节是最小的存储单位。(故数组中每个元素的地址总比前一个大。)    ...

c++ 指针point 和引用reference的区别

reference point
  • mlyjqx
  • mlyjqx
  • 2017年01月12日 16:17
  • 176

Java中文分词工具AnsjSeg使用

中文分词是进行中文文本分析的一个重要步骤。对于Java语言,有许多可选的分词工具,如中科院计算所的NLPIR(原ICTCLASS)、盘古分词、IKAnalyzer、PaodingAnalyzer,其中...
  • hfut_jf
  • hfut_jf
  • 2015年01月14日 22:26
  • 4865

Video Analysis 相关领域介绍之Video Captioning(视频to文字描述)

之前两次分别介绍了video analysis中的action recognition 以及 temporal action detection 这两个领域。这两个领域算是对视频mid-level的理...
  • wzmsltw
  • wzmsltw
  • 2017年05月05日 10:58
  • 2224

A Companion To Analysis (数学分析)

  • 2010年05月09日 01:07
  • 3.28MB
  • 下载

MLY -- 13.Error analysis:look at dev set examples to evaluate ideas

当你在玩你的猫app时,你发现几个把狗狗分类成猫的例子。但是有些狗狗真的很像猫! 你的团队成员提出结合第三方软件将会使系统在处理狗狗图片上更好。但这将会花费一个月,团队成员对此很是热情。你应...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:指针分析/Point-to Analysis/Reference Analysis
举报原因:
原因补充:

(最多只允许输入30个字)