C#静态分析,变量/参数可能的取值

8
在类似以下示例的代码中,我希望能够静态分析代码以确定传递给SpecialFunction()的可能值列表。
SpecialFunction(5); // A

int x = 5;
SpecialFunction(x); // B

int x = 5;
x = condition ? 3 : 19;
SpecialFunction(x); // C

我已经能够将C#解析成抽象语法树,我已经可以处理像A这样的情况,我猜我可以追踪初始值分配以猜测B的情况,但是像C这样简单的情况似乎很快就会变得复杂。

我几乎可以确定在所有情况下我们都无法静态地解决x,并且这是可以接受的。我想知道尝试解决它的策略,以及识别无法解决的方法。如果需要包括类级别字段和多线程怎么办?闭包?如果我们知道对于所有可能值的集合X中,|X| < 50,是否有帮助?

根据@Vladimir Perevalov的建议,如何将Pex中的概念应用于查找目标代码点的可能值(而不是Pex似乎发现的导致未检查异常情况的代码路径和值)?


1
不要认为静态分析的“职责”是猜测指定参数值范围的可能失败/成功,这很可能是“动态分析”的“职责”。但即使如此,在这种情况下,您只处理一对*参数,如果您处理一个函数,例如,IEnumerable<int>GetValuesForx(...)呢? - Tigran
@Tigran - 运行或模拟程序(或片段)不是一个选项。此外,显然有一些情况下静态分析可以提供答案 - 也显然有一些情况下它无法提供答案。我正在尝试确定和实现它可以提供答案的情况。 - Jason Kleban
1个回答

4
你需要的是全局数据流分析(“哪些值赋值/副作用到达了哪些使用点”)和某种范围分析(“总结可以到达一个点的值的集合”)。计算数据流需要具备完整的C#前端、本地控制和数据流分析,然后将这些答案拼接成全局数据流分析。范围分析要求您首先定义如何编码可能值的集合;允许哪种规范系统?最简单的只是一组值,往往会爆炸。中间规范方案可能是像OP的单关系到常量的方案,例如,“x < 50”。任何这样的有限方案的问题在于,如果存在其他感兴趣的谓词(如果x总是奇数,则单关系到常量只能将其建模为“x < infinity”,这显然没有帮助),那么值集的丰富性可能导致您得到无用的答案。因此,您希望选择一个规范方案,它足够复杂以模拟您感兴趣的值类型。但是,随着您的规范方案变得更加复杂,正确推断这些事实的机制也变得更加复杂,因此您不能使其过于复杂。
大多数可用的分析工具都没有这样的分析功能,更不用说向您公开了。PEX可能确实有这样的机制;如果您很幸运,它也是公开的。
我们的DMS软件重构工具包具有通用解析、符号表构建、控制/数据流分析甚至范围分析机制(规范:x < k1*a+k2*b,其中k1和k2是常数,a和b是其他程序变量,在x消耗的地方可见)。DMS具有C#、Java、GNU C和COBOL前端,我们实际上已经通过收集(静态分析!)针对这些语言特定的事实并将这些事实提供给通用机制,为GNU C和IBM Enterprise COBOL(以及部分Java 7)实例化了这个机制。我们尚未为C#实例化此机制。但是,如果您无法从其他来源获得满意的答案,这很可能就是答案。

我在使用MSR Roslyn时取得了相当大的进展。我仅将其用于解析到AST,并且进行了自己的(有缺陷的)推理,而没有太多的努力。我认为Roslyn可以为我做更多的事情,但它的文档不是很好。这已经足够作为概念验证。如果这个项目继续下去,我可能会与贵公司联系。 - Jason Kleban
我猜Roslyn的全局流分析很少。就我所知,C#大多是JIT编译器。 - Ira Baxter
JITed-ness与全局流分析有什么关系? - Jason Kleban
@Jason:1)如果你正在进行JIT编译,将源代码转换为pCode(CIL)的工具(我认为Roslyn就是这样的工具)不需要编译高度优化的pCode。2)通常你会得到非常好的分离编译,这对全局优化是不利的。人们期望运行时JIT执行器根据动态测量进行更复杂的分析;它可能有全局优化,但至少可以访问“整个”程序(除了动态加载的内容)。 - Ira Baxter

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接