我的代码类似于:
if conditionA(x, y, z) then doA()
else if conditionB(x, y, z) then doB()
...
else if conditionZ(x, y, z) then doZ()
else throw ShouldNeverHappenException
我想验证两件事(使用静态分析):
conditionA, conditionB, ..., conditionZ
互相排斥(即两个或多个条件不可能在同一时间内成立)。你能推荐一个工具和/或我可以(轻松)这样做的方法吗?
我会比“使用Prolog”或“使用Mathematica”感谢更详细的信息......; - )
更新
假设conditionA, conditionB, ..., conditionZ
是(纯)函数,x,y,z具有“原始”类型。
答案 0 :(得分:2)
您想要做的第1项是一个风格问题。即使条件不是唯一的,该程序也是有意义的。就个人而言,作为静态分析工具的作者,我认为用户得到足够的误报而不试图强制它们的风格(并且因为另一个程序员会故意写重叠条件,对于其他程序员你会问的是误报警) 。这就是说,有一些可配置的工具:对于其中一个,您可以编写一条规则,说明在遇到此构造时案例必须是独占的。正如Jeffrey建议的那样,您可以将代码包装在一个上下文中,在该上下文中计算一个布尔条件,如果没有重叠则为true,并检查该条件。
第2项不是样式问题:您想知道是否可以引发异常。
这个问题在理论上和实践中都很困难,因此工具通常会放弃至少一个正确性(如果出现问题则永远不会发出警告)或完整性 (从不警告不发行)。如果变量的类型是无界整数,则可计算性理论会声明分析器不能正确和完整,并且终止所有输入程序。但足够的理论。有些工具会放弃正确性和完整性,但这并不意味着它们也没用。
正确的工具示例是Frama-C的值分析:如果它说某个语句(例如elseifs序列中的最后一个案例)无法访问,则表示它无法访问。它不完整,所以当它没有说最后一个语句无法访问时,你就不知道了。
完整工具的一个示例是Cute:它使用所谓的concolic方法自动生成测试用例,旨在实现结构覆盖(也就是说,它会或多或少尝试尝试一旦所有其他案例被采取,就生成激活最后一个案例的测试。因为它生成测试用例(每个测试用例都是实际执行代码的单个,确定的输入向量),所以它永远不会警告无问题。这就是完成的意思。但它可能无法找到导致最后一个语句到达的测试用例,即使有一个:它不正确。
答案 1 :(得分:1)
这似乎与解决3-sat方程是同构的,这是NP-hard。不幸的是,静态分析器不太可能试图覆盖这个域。
答案 2 :(得分:1)
在一般情况下,这就像@Michael Donohue所说的那样 - 一个NP难题。
但是如果你只有合理数量的条件要检查,你可以写一个检查所有条件的程序。
for (int x = lowestX; x <= highestX; x++)
for (int y ...)
for (int z ...)
{
int conditionsMet = 0;
if conditionA(x, y, z) then conditionsMet++;
if conditionB(x, y, z) then conditionsMet++;
...
if conditionZ(x, y, z) then conditionsMet++;
if (conditionsMet != 1)
PrintInBlinkingRed("Found an exception!", x, y, z)
}
答案 3 :(得分:1)
假设你的条件是布尔表达式(和/或/不)超过布尔值谓词X,Y,Z,你的问题可以通过符号布尔评估引擎轻松解决。
关于他们是否涵盖所有案件的问题通过对所有条件进行解构并且询问是否是重言式来回答。 Wang的算法做得很好。
关于它们是否相交的问题是成对回答的;对于公式a和b, 象征性地构建一个&amp; b == false并再次申请王的重言式考试。
我们使用DMS Software Reengineering Toolkit对C中的预处理器条件进行类似的布尔值计算(部分评估).DMS提供了解析源代码的能力(如果您打算在大型代码中执行此操作,则很重要)随着时间的推移修改你的程序时反复编写和/或重复,提取程序片段,象征性地组合它们,然后应用重写规则(执行布尔简化或算法,如王的)。