这篇文章详细描述了在 Achieving Accuracy and Scalability Simultaneously in Detecting Application Clones on Android Markets 这篇文章中新提出的一个东西,姑且就叫做centroids algorithm(质心算法)
CFG是control flow graph的简写,在中文翻译叫做 * 控制流图 *
控制流图是程序依赖图(PDG program dependence graph)的一个部分.程序的依赖总共有两种一种是数据依赖(data dependency)另外一种是方法之间的相互调用关系,我们把这种关系叫做(control dependency)。
数据依赖(data dependency)指的是例如在一个代码块中存在着两条语句(statement)我们把这两条语句分别叫做S1和S2. S1当中有一个数据data1 它的取值完全是靠S2这条语句中的data2来决定的。比如说我们来看一段代码
》》》》》
int a;
int b;
....
if(b > 3)
a = 2;
else
a = 1;
从上面这段代码我们可以看出a的取值完全是依赖于b的取值的。
我们把具有数据依赖的这些调用关系构成的图叫做数据流图(data flow graph)
如果两条语句,其中一条语句的执行完全依赖于另一条语句的执行,那么我们把这种依赖的关系叫做控制依赖。由这种控制关系构成的图我们把它们叫做(control flow graph)
今天主要讲的就是控制流图(control flow graph)。
但是由于控制流图的英文缩写是CFG这里描述的是3D-CFG,表示的是3维空间的控制流图。
一个控制流图是一个方法,里面的每一个基本代码块语句我们把它们设置为一个节点。
具体的CFG更详细的讲解我们可以参看:
https://en.wikipedia.org/wiki/Control_flow_graph
- 每个节点的语句块只能有一个入口一个出口
- 不能含有goto语句,不能含有分支语句,不能还有循环语句
还有一篇比较好的blog,我们可以看这里:
程序控制流图链接
下面的内容均来自这篇博客:
定义 基本块:是一个最大化的指令序列,程序执行只能从这个序列的第一条指令进入,从这个序列的最后一条指令退出。
确定基本块的原则:
1) 遇到程序、子程序的第一条指令或标号语句,结束当前基本块,并将该语句作为一个新块的第一条语句。
2) 遇到goto语句、分支语句、循环语句,将该语句作为当前块的最后一条语句,并结束当前块。
3) 遇到其他语句直接将其加入到当前基本块。
定义 控制流图CFG(Control Flow Graph):是以基本块为结点的有向图G=(N, E),其中N是结点集合,表示程序中的基本块;E是边的集合,如果从块U的出口转向块V,则从U到V有一条有向边UàV,表示从结点U到V存在一条可执行路径,称U为V的前驱结点,V为U的后继结点。也就代表在执行完结点U中的代码语句后,有可能顺序执行结点V中的代码语句。
常见控制语句对应的控制流图:
看一段源程序:
int fib(int m)
{ int f0=0,f1=1,f2,i;
if(m<=1){return m;}
else
{ for(i=2;i<=m;i++)
{ f2=f0+f1;
f0=f1;
f1=f2;
}
return f2;
}
}
中间表示:
receive m
f0 ← 0
f1 ← 1
if m<=1 goto L3
i ← 2;
L1:if i<=m goto L2
return f2
L2:f2 ← f0+f1
f0 ← f1
f1 ← f2
i ← i+1
goto L1
L3:return m
在这篇文章中,作者借用了物理学当中重心(centroid)的概念来迁移到我们的程序设计当中。在物理学当中,我们有个时候把物体抽象成一个质点,理想化模型中,我们认为物体的质点全部都集中在重心上。规则物体并且质量分布均匀的物体它的几何中心就是我们物体的重心。
对于两个完全一样的物体,那么物体的重心应该是完全一样的,对于稍微变化的两个物体,那么他们的重心应该也不会变化太多。就是基于这两点观察,作者引入了centroid来代替整个CFG。便于快速的比较。
3D-CFG也是一种特殊的CFG每个节点都有一个对应的三维坐标。在这里3D-CFG中的表示的是一个基本代码块.
我是自学的关于这篇文章。如果有什么理解的不对的,欢迎您提出宝贵意见和指点,非常感谢。
这个坐标可以看成是一个向量 (x,y,z)
其中X表示的是这个节点在CFG图中的编号
y表示的是这个节点的出度
Z表示的是这个节点所在的循环的深度。
对于一个CFG,第一个开始的节点标志位1。
对于有分支的节点,假设这个节点的编号是N,那么这个节点下面的分支最多的节点我们把它设置为N+1。如果这个节点N下面的节点当中有一些节点的分支是相同的,那么我们选择这个节点当中语句最多的设置为N+1号节点,假设这些分支节点不仅分支相通,就连里面的语句也是相同的这个时候我们就看里面的第一条语句的二进制值谁的比较大。我们把比较大的那个二进制值设置为第N+1号结点。
一个节点下面有多个分支的情况,对其编号,为了表述的清楚一点,我们总结成列表:
1.先看分支数目
2.看分支中的每一个基本代码块(basic code block)中含有的语句的个数stmt
3. 在语句条数一直的情况下看第一条语句的二进制代码值。
例如上面这个图,起始的结点是结点A我们为这个图设置一个编号叫做1,之后是我们的结点B,它的编号是2。在B的下面有4个结点,我们依次比较结点的分支,我们发现结点D,F有相同的分支,且是分支当中最大的,我们设置结点的编号根据每个结点当中的语句条数来选项编号,我们假设F这个节点的方法中它的statement比较多,所以我们选择F作为我们的3号节点。编号的规则我们按照上述规则来
在这里有一点是需要详细说明的,那就是循环的深度,我理解的是对于嵌套循环来说,比如说三层嵌套,那么第三层的嵌套循环的深度就是3。
我们举文章中的例子来详细的说明3D-CFG:
图3的左边这个图a,我们依次给他们编号:
结点A
它是入口,所以x的坐标是1,并且有一个出度所以Y的坐标也是1,之后我们看没有宰任何循环中,所以A的坐标是(1,1,0)
这个时候自然而然的是编码结点B
结点B
结点B的X坐标也是很好的确定是2,结点B有两个出度所以Y的坐标是2,结点B在一层循环里,所以结点B的坐标是(2,2,1)
之后我们看需要先编码谁?对于节点C,E 都是B的分支节点,这个时候我们需要判断谁的分支比较多,根据文章列出来的规则。
明显我们可以看出是节点C的分支比较多:
所以我们要先编码结点C。
结点C
顺其自然,结点C的X坐标是3,Y的坐标是2,有两个出度,C也在一个循环中,所以C的Z坐标是1 ,得出C的坐标是(3,2,1)
编码完结点C,我们需要编码结点D,这个有点类似深度遍历算法,除了选择编码的地方。
结点D
结点D的X坐标是4,Y坐标是1,在一个循环中所以Z是1。这个时候D的坐标是(4,1,1)
这个时候我们再来编码结点E
E(5,1,0)
F(6,0,0)
注意: 在这里我们需要注意的是B,C的Z坐标是1而不是2,因为他们都在一层循环里,而不是在嵌套的循环里
这个是质心的定义。在这里 e(p,q) 指代的是 3D-CFG中的两个结点之间的边,P点是起点,q点是终点。 ϖp 表示的的是基本代码块p中的语句stmt(statement)的个数。我们假设从 ϖA 到 ϖF 对应的权值设置为5,3,4,2,1,0。
之后我们计算一下每条边权值的总和:
ϖ = (5+3)+(3+4)+(3+1)+(4+3)+(4+2)+(2+3)+(1+0) = 38.
这个时候我们就可以计算centroid的x的值:
Cx=5×1+3×2×5+4×3×+2×4×2+1×5×238=2.5526
本章中涉及到的公式的Latex代码
$ \varpi_{p} $
$ \varpi $ = (5+3)+(3+4)+(3+1)+(4+3)+(4+2)+(2+3)+(1+0) = 38.
$C_{x}=\frac{5\times1+3\times2\times5+4\times3\times+2\times4\times2+1\times5\times2}{38}=2.5526 $
依次计算向量得到这个图的centroid的向量表示:
c=<2.5526,1.7105,0.8158,38>
如果明白了整个算法,下面要做的事情就是设计好数据结构,开始编码构建CFG和设计数据库,计算出我们的APK的centroid保存到数据库中。
之后有时间我在继续更新整个设计代码的思路和数据库的设计部分代码。
一群嗜血的蚂蚁被腐肉所吸引
我面无表情看孤独的风景
失去你爱恨开始分明
失去你还有什么事好关心
当鸽子不再象徵和平
我终於被提醒
广场上餵食的是秃鹰
我用漂亮的押韵
形容被掠夺一空的爱情
乌云开始遮蔽夜色不不干净
送你的白色玫瑰
在纯黑的环境凋零
乌鸦在树枝上诡异的很安静
静静听我黑色的大衣
想温暖你日渐冰冷的回忆
老去后还爱你
为你弹奏萧邦的夜曲
纪念我死去的爱情
跟夜风一样的声音
心碎的很好听
手在键盘敲很轻
我给的思念很小心
你埋葬的地方叫幽冥
对你心跳的感应
还是如此温热亲近
那些断翅的蜻蜓散落在这森林
而我的眼睛没有丝毫同情
失去你泪水混浊不清
失去你我连笑容都有阴影
风在长满青苔的屋顶
嘲笑我的伤心
像一口没有水的枯井
我用凄美的字型
描绘后悔莫及的那爱情
为你弹奏萧邦的夜曲
纪念我死去的爱情
跟夜风一样的声音
心碎的很好听
手在键盘敲很轻
我给的思念很小心
为你弹奏萧邦的夜曲
纪念我死去的爱情
而我为你隐姓埋名在月光下弹琴
对你心跳的感应还是如此温热亲近