什么是IDFS下的分配函数,为什么指针分析是非分配函数



我目前正在用Java做一个程序间分析项目,我正在考虑使用IFDS求解器来计算程序的控制流图。我发现很难理解IFDS框架和图可达性描述中涉及的数学问题。我在一些地方读到,使用这个解算器不可能计算程序集的点,因为"指针分析是一个非分布式问题。"[1]其他来源说,这通常是专门针对"强更新"的,我可以从中收集到的是字段写入语句。

我想我基本上可以遵循解算器如何计算边并计算出数据流事实。但我不太明白这是什么:f(AõB)=f(A)õf(B)在实际意义上是分配函数的定义,因此,指向分析处理非分配函数意味着什么。

链接源[1]给出了一个特定于字段写入语句的示例:

A a = new A();
A b = a;
A c = new C();
b.f = c;

它声称,为了对b.f的赋值进行推理,还必须考虑基b的所有别名。我可以遵循这一点。但我不明白的是,这个动作的特性是什么,使它成为非分配的。

[2]中的一个类似(我认为)例子:

x = y.n

其中,在语句之前有指向边y-->obj1和obj1.n-->obj2的点(其中obj1与2是堆对象)。他们声称

如果我们独立地考虑每个输入边,就不可能正确地推断出边x-->obj2应该在语句之后生成。该语句的流函数是一个点到图的函数,不能分解为每条边的独立函数,然后合并以获得正确的结果。

我想我几乎明白了,至少第一个例子是这样说的,但我没有理解分布式函数的概念,这阻碍了我了解全貌。有人能在不使用我很难理解的集合论的情况下,在指针分析的实际基础上解释什么是分配函数或非分配函数吗?

[1]http://karimali.ca/resources/pubs/conf/ecoop/SpaethNAB16.pdf

[2]http://dl.acm.org/citation.cfm?doid=2487568.2487569(付费墙,抱歉)

流函数的分布性定义为:f(aπb)=f(a)πf(b),其中π是合并函数。在IFDS中,π被定义为集合并集Ş。这意味着,无论您是否在流函数之前或之后应用merge函数,最终都会得到相同的结果。

在传统的数据流分析中,您要遍历CFG的语句并传播数据流事实集。因此,使用流函数f,对于每个语句,您计算f(in,stmt)=out,以及要保留的信息集的in和out(例如:对于in集{(a,allocA),(b,allocA)}-表示对象a和b的分配位置是allocA,以及语句"b.f=new X();"-我们将其命名为allocX,您可能会得到输出集{(a,allocA),(b,allocAA),(a.f,allocX),(b.f,alloxX)},因为a和b是别名)。

IFDS将内集分解为其各自的数据流事实。因此,对于每一个事实,不是用整个in集运行一次流函数,而是在in集的每个元素上运行它:∀d∈in,f(d,stmt)=out_d。然后,框架将所有out_d合并到最终outset中。这里的问题是,对于每个流函数,您都无法访问整个内集,这意味着对于我们上面给出的例子,在语句上运行流函数f((a,allocA))将产生第一个外集{(a,alocA)},f(((b,allocA))将产生第二个外集{(b,alocAA)},f(0)将产生第三个外集((0),(b.f,allocX)}。因此,合并结果后的全局输出集将是{(a,allocA),(b,allocB),(b.f,allocX)}。我们缺少事实{(a.f,allocX)},因为当运行流函数f(0)时,我们只知道事实是0,并且语句是"b.f=new X();"。因为我们不知道a和b引用了分配站点allocA,所以我们不知道它们是别名的,因此我们不知道a.f也应该在语句之后指向allocX。

IFDS是在分布性假设下运行的:在运行流函数后合并输出集的结果应该与在运行流功能前合并输入集的结果相同。换言之,如果你需要组合来自输入集上多个元素的信息,以在输出集中创建特定的数据流事实,那么你不是分布式的,不应该在IFDS中表达你的问题(除非你做了一些事情来处理这些组合情况,就像你所说的[1]论文的作者所做的那样)。

相关内容

  • 没有找到相关文章

最新更新