1.本发明属于软件工程领域,涉及静态程序分析技术和循环上界分析技术,特别涉及一种基于高精度静态程序分析的循环上界计算方法。
背景技术:2.循环结构是在一定条件下反复执行某段程序的流程结构,被反复执行的程序被称为循环体。循环语句是由循环体及循环的终止条件两部分组成的。循环上界指的是循环语句的最多执行次数。判断循环上界最大值,对于实时系统十分重要,过多的循环执行次数会导致程序执行缓慢,系统无法实时响应,所以很多应用场景要求对循环上界进行约束,通过静态程序分析估算程序的循环上界可以在不运行程序的情况下分析循环最多执行次数,并对循环上界次数超过阈值的循环语句给出警报,从而在不运行程序的情况下评估程序的运行效率或者提示开发者对循环语句进行优化。
3.本发明使用到的关键技术有数据流分析。数据流分析首先需要构建控制流图来反映所有基本块执行流,以及构建函数调用图来反映函数调用的关系。根据变量在程序的控制流图、函数调用图上如何传播,进一步收集、计算和分析得到信息。
4.本发明公开一种基于静态程序分析的流敏感、上下文敏感的循环上界分析方法。首先定位程序中的循环语句并识别循环控制变量,其次分析循环变量的数据依赖关系,然后对循环上界计算依赖表达式中变量的可能值进行分析,之后递归计算循环上界计算依赖表达式的可能值,最后依据循环结构归纳循环上界的公式并根据循环上界所依赖表达式的取值计算最终结果。
技术实现要素:5.目前对于循环语句的分析,很多都是侧重于验证程序的正确性,如验证循环语句是否是死循环。而对于循环上界的计算,目前只能针对循环依赖表达式为常量以及循环结构是简单循环的情况,而对于包含复杂表达式和嵌套循环的循环语句,无法计算较为精确的循环上界结果。为解决上述问题,本发明采用数据流分析以及递归算法,对复杂循环依赖表达式的值进行了分析计算,并归纳总结了不同循环模式的循环上界计算方法,本发明具体通过以下技术方案来实现:
6.一种基于高精度静态程序分析的循环上界计算方法,其特征在于,包括以下步骤:
7.步骤1):定位程序中的循环语句并识别循环控制变量;通过静态程序分析定位程序中的循环语句,识别循环语句的模式,根据for语句、while语句、do-while语句的语法模式,提取不同模式循环语句中的循环控制变量;
8.步骤2):分析循环变量的数据依赖关系;根据for语句、while语句、do-while语句的语法模式,分析循环变量的数据依赖关系,找出所有循环上界计算所依赖的表达式,包括分析循环初始表达式、循环终止表达式以及循环增量表达式;
9.步骤3):对循环上界依赖表达式中变量的可能值进行分析;进行过程内和过程间
的数据流分析,对基本类型变量的可能值进行分析,在数据流分析过程中需要计算表达式的值则调用下一步骤即步骤4)的方法进行计算;
10.步骤4):递归计算循环依赖表达式的可能值;其中对于表达式中的普通变量则调用步骤3)的方法分析出具体值;
11.步骤5):依据循环结构归纳循环上界的公式计算最终结果;根据for语句、while语句、do-while语句的语法模式,使用所述步骤4)的方法分析计算循环上界依赖表达式的可能值,分别针对简单循环、嵌套循环、连锁循环归纳计算循环上界的公式并计算最终结果。
12.上述的基于高精度静态程序分析的循环上界计算方法,其特征在于,所述步骤1)定位程序中的循环语句并识别循环控制变量具体包括以下步骤:
13.步骤11):将程序源码转换成抽象语法树作为输入,在抽象语法树的基础上构建程序的控制流图和函数调用图;遍历控制流图中的语句,遍历到for循环语句、while循环或do-while循环语句则进行进一步的分析;
14.步骤12):对于for循环语句,形式为for(初始表达式;循环条件;增量表达式){循环体;};若for语句存在初始表达式,提取初始化变量或赋值表达式的左值作为循环控制变量;若for语句存在循环条件且循环条件为关系表达式,提取关系表达式的左值作为循环控制变量;若for语句存在增量表达式,提取自增或自减的变量或者提取赋值语句的左值作为循环增量表达式;若三者都不存在,则遍历循环体查找变化的变量,包括自增、自减语句的变量或复合赋值语句中的左值;
15.步骤13):对于while循环语句,形式为while(循环条件){循环体};若循环条件为关系表达式,提取表达式左值作为循环控制变量,若循环条件为单变量,则该变量即为循环控制变量;
16.步骤14):对于do-while循环语句,形式为do{循环体;}while(循环条件);若循环条件为关系表达式,提取表达式左值作为循环控制变量,若循环条件为单变量,则该变量即为循环控制变量。
17.上述的基于高精度静态程序分析的循环上界计算方法,其特征在于,所述步骤2)分析循环变量的数据依赖关系具体包括以下步骤:
18.步骤21):对于for循环语句,若循环控制变量是在for循环初始表达式中进行初始化或赋值,则直接获取初始化语句或赋值语句的右值作为循环初始表达式,否则调用所述步骤3)的方法进行数据流分析得到循环控制变量在进入循环前的值;若for语句存在循环条件且循环条件为关系表达式,提取关系表达式的右值作为循环终止表达式,否则遍历循环体查找是否存在break或return语句,提取其所在if语句的条件表达式中的右值作为循环终止表达式;根据所述步骤1)中定位的循环增量语句,若增量语句形式为自增或自减表达式,则设置循环增量值为1,若增量语句形式为复合赋值语句,则提取赋值语句的右值作为循环增量表达式;
19.步骤22):对于while循环语句;调用所述步骤3)的方法通过数据流分析得到循环控制变量在进入循环前的值,该值即为循环语句的循环初始值;若循环条件为关系表达式,提取表达式右值作为循环终止表达式,若循环条件为单变量,则遍历循环体查找是否存在break或return语句,提取其所在if语句的条件表达式中的右值作为循环终止表达式;分析循环体查找对循环控制变量的值进行更新的语句,对于自增、自减语句,则设置循环增量值
为1,对于复合赋值语句,则提取其右值作为循环增量表达式;
20.步骤23):对于do-while循环语句,和while语句提取循环初始表达式、循环终止表达式以及循环增量表达式的方式相同。
21.上述的基于高精度静态程序分析的循环上界计算方法,其特征在于,所述步骤3)对循环上界依赖表达式中变量的可能值进行分析具体包括以下步骤:
22.步骤31):分别定义初始化语句、赋值语句、复合赋值语句、自增自减语句、循环语句的数据流转换函数;其参数为待分析语句、变量在执行语句前的值,函数返回值为变量在执行语句后的值;
23.步骤32):对于初始化语句和赋值语句的数据流转换函数,通过调用所述步骤4)的方法计算初始化语句或赋值语句的右值,将该值作为执行语句的后值;
24.步骤33):对于复合赋值语句的数据流转换函数,通过调用所述步骤4)的方法计算复合赋值语句的右值,根据运算符的类型对前值进行+=、-=、/=、*=的运算,将运算结果作为执行语句的后值;
25.步骤34):对于自增自减语句的数据流转换函数,根据单目运算符的类型,将前值加一或减一作为执行语句后的值;
26.步骤35):对于循环语句的数据流转换函数,需要对循环体中的语句进行数据流分析,将每一次执行完循环体的后值作为下一次循环的前值,如此执行当前循环的循环上界次;由于顺序分析所有循环语句,所以当前循环已经经过了循环上界分析,并记录了循环上界结果;
27.步骤36):对于变量在函数内进行初始化的情况,进行过程内的数据流分析;遍历函数体的控制流图,分析语句中是否存在待分析变量,若存在则根据语句类型传入对应的数据流转换函数分析变量后值;
28.步骤37):对于变量来自于形参的情况进行过程间的数据流分析;根据函数调用图,找到当前函数的所有调用者以及函数调用点,根据变量在形参中的位置,匹配函数调用点的实参;调用所述步骤3)递归地分析该实参可能的最大值或最小值,并将分析结果传递给形参;再对该变量进行过程内的数据流分析。
29.上述的基于高精度静态程序分析的循环上界计算方法,其特征在于,所述步骤4)递归计算循环依赖表达式的可能值具体包括以下步骤:
30.步骤41):对于普通变量,调用所述步骤3)中的方法分析该变量的可能值;
31.步骤42):对于双目运算表达式,若表达式为算术运算,递归调用所述步骤4)计算表达式左值和右值,根据运算符类型对表达式左值和右值进行相应的加、减、乘、除、取余运算;若表达式为关系运算,递归调用所述步骤4)计算表达式左值和右值,根据运算符类型对表达式左值和右值进行相应的相等、不等、大于、小于、大于等于、小于等于的关系判断,得到最终结果;
32.步骤43):对于三目运算表达式,形式为cond?x:y,递归调用所述步骤4)计算条件cond,如果cond的值为true,递归调用所述步骤4)计算x的值并返回;否则,递归调用所述步骤4)计算y的值并返回;
33.步骤44):对于函数调用表达式,定位该函数的函数体并遍历函数体的控制流图,得到该函数的返回表达式,递归调用所述步骤4)计算该表达式的值并返回。
34.上述的基于高精度静态程序分析的循环上界计算方法,其特征在于,所述步骤5)依据循环结构归纳循环上界的公式计算最终结果具体包括以下步骤:
35.步骤51):根据for语句、while语句、do-while语句的语法模式,调用所述步骤4)的方法,分析循环控制变量初始表达式和循环控制变量增量表达式的可能值;
36.步骤52):对于简单循环,根据公式
37.loop_upbound=|end_value-init_value|/incre_value计算出当前循环的循环次数;其中loop_upbound为循环上界结果,end_value为循环控制变量终止值,init_value为循环控制变量初始值,increment_value为循环控制变量增量值;
38.步骤53):对于嵌套循环,总迭代次数等于外层循环变量每种取值情况下的内层循环次数的加和;考虑内层循环的初始表达式或终止表达式为外层循环控制变量的情况,对于内层循环初始表达式可变的情况,若内层循环递增嵌套循环计算公式为若内层循环递减嵌套循环计算公式为其中i为内层循环初始表达式,out_init为外层循环的初始值,out_end为外层循环的终止值,in_end为内层循环的终止值;对于内层循环终止表达式可变的情况,若内层循环递增,嵌套循环计算公式为若内层循环递减,嵌套循环计算公式为其中i为内层循环终止表达式,in_init为内层循环的初始值;
39.步骤54):对于连锁循环,若各循环之间没有依赖关系,则按照分析简单循环或嵌套循环的方法对各循环语句进行独立分析;若循环之间存在依赖关系,即后续循环上界依赖于前面循环中进行了更新的变量,方法是顺序分析循环语句,记录已分析循环语句的循环上界,即可得到该循环语句的数据流转换函数,具体来说,将每一次执行完循环体的后值作为下一次循环的前值,如此执行当前循环的循环上界次就能够得到循环语句的后值;将该值作为下一个循环依赖变量的前值即可分析下一个循环的循环上界;
40.步骤55):本方法考虑了使用频率较高的基本表达式,对于没有考虑到的表达式状态或者存在变量来自于外部输入而无法计算表达式确定值的情况,则输出表达式字符串以及分析过程中得到的信息。
41.上述的基于高精度静态程序分析的循环上界计算方法,其特征在于:在所述步骤3)对循环上界依赖表达式中变量的可能值进行分析的具体步骤中,考虑过程间的数据流分析,对于循环相关变量来自于形参的情况可以分析到调用点的实参。
42.上述的基于高精度静态程序分析的循环上界计算方法,其特征在于:在所述步骤4)递归计算循环依赖表达式的可能值的具体步骤中,考虑循环相关表达式是复杂表达式的情况,计算由一些使用频率较高的基本表达式排列组合形成的复杂表达式的结果。
43.上述的基于高精度静态程序分析的循环上界计算方法,其特征在于:在所述步骤5)依据循环结构归纳循环上界的公式计算最终结果的具体步骤中,总结归纳了内层循环的循环相关变量是外层循环控制变量的循环上界计算方式,针对一些使用频率较高模式的嵌套循环能给出较精确的结果;对于循环之间存在依赖的连锁循环也给出了高精度的循环上
界计算方法。
44.本发明通过采用以上技术方案,可以具体得到以下有益效果:
45.1、本方法考虑过程间的数据流分析,对于循环相关变量来自于形参的情况可以分析到调用点的实参。
46.2、本方法考虑循环相关表达式是复杂表达式的情况,可以计算由一些使用频率较高的基本表达式排列组合形成的复杂表达式的结果。
47.3、本方法考虑嵌套循环中,内层循环的循环相关变量是外层循环控制变量的情况,针对一些使用频率较高模式的嵌套循环能给出较精确的结果。
附图说明
48.图1为本发明基于高精度静态程序分析的循环上界计算方法的原理图。
49.图2为本发明基于高精度静态程序分析的循环上界计算方法的流程图。
具体实施方式
50.为了使本领域技术人员更好地理解本发明,下面结合附图和具体实施例对本发明做进一步详细的说明。
51.本实施例的基于高精度静态程序分析的循环上界计算方法,原理图和流程图如图1和图2所示,其具体步骤为:
52.步骤1):通过静态程序分析定位程序中的循环语句。根据for语句、while语句、do-while语句的语法模式,提取不同模式循环语句中的循环控制变量。
53.所述步骤1)具体包括以下步骤:
54.步骤11):将程序源码转换成抽象语法树作为输入,在抽象语法树的基础上构建程序的控制流图和函数调用图。遍历控制流图中的语句,遍历到for循环语句、while循环或do-while循环语句则进行进一步的分析;
55.步骤12):对于for循环语句,形式为for(初始表达式;循环条件;增量表达式){循环体;}。若for语句存在初始表达式,提取初始化变量或赋值表达式的左值作为循环控制变量;若for语句存在循环条件且循环条件为关系表达式,提取关系表达式的左值作为循环控制变量;若for语句存在增量表达式,提取自增或自减的变量或者提取赋值语句的左值作为循环增量表达式;若三者都不存在,则遍历循环体查找变化的变量,包括自增、自减语句的变量或复合赋值语句中的左值。
56.步骤13):对于while循环语句,形式为while(循环条件){循环体}。若循环条件为关系表达式,提取表达式左值作为循环控制变量,若循环条件为单变量,则该变量即为循环控制变量。
57.步骤14):对于do-while循环语句,形式为do{循环体;}while(循环条件);若循环条件为关系表达式,提取表达式左值作为循环控制变量,若循环条件为单变量,则该变量即为循环控制变量。
58.步骤2):根据for语句、while语句、do-while语句的语法模式,分析变量的数据依赖关系,找出所有循环上界分析所依赖的表达式,包括分析循环初始表达式、循环终止表达式以及循环增量表达式。
59.所述步骤2)具体包括以下步骤:
60.步骤21):对于for循环语句,若循环控制变量是在for循环初始表达式中进行初始化或赋值,则直接获取初始化语句或赋值语句的右值作为循环初始表达式,否则调用下一步骤即步骤3)的方法进行数据流分析得到循环控制变量在进入循环前的值;若for语句存在循环条件且循环条件为关系表达式,提取关系表达式的右值作为循环终止表达式,否则遍历循环体查找是否存在break或return语句,提取其所在if语句的条件表达式中的右值作为循环终止表达式。根据步骤1中定位的循环增量语句,若增量语句形式为自增或自减表达式,则设置循环增量值为1,若增量语句形式为复合赋值语句,则提取赋值语句的右值作为循环增量表达式。
61.步骤22):对于while循环语句。调用步骤3)的方法通过数据流分析得到循环控制变量在进入循环前的值,该值即为循环语句的循环初始值。若循环条件为关系表达式,提取表达式右值作为循环终止表达式,若循环条件为单变量,则遍历循环体查找是否存在break或return语句,提取其所在if语句的条件表达式中的右值作为循环终止表达式。分析循环体查找对循环控制变量的值进行更新的语句,对于自增、自减语句,则设置循环增量值为1,对于复合赋值语句,则提取其右值作为循环增量表达式。
62.步骤23):对于do-while循环语句,和while语句提取循环初始表达式、循环终止表达式以及循环增量表达式的方式相同。
63.步骤3):进行过程内和过程间的数据流分析,对基本类型变量的可能值进行分析,在数据流分析过程中需要计算表达式的值则调用下一步骤即步骤4)的方法进行计算。
64.所述步骤3)具体包括以下步骤:
65.步骤31):分别定义初始化语句、赋值语句、复合赋值语句、自增自减语句、循环语句的数据流转换函数。其参数为待分析语句、变量在执行语句前的值,函数返回值为变量在执行语句后的值。
66.步骤32):对于初始化语句和赋值语句的数据流转换函数,通过调用步骤4)的方法计算初始化语句或赋值语句的右值,将该值作为执行语句的后值。
67.步骤33):对于复合赋值语句的数据流转换函数,通过调用步骤4)的方法计算复合赋值语句的右值,根据运算符的类型对前值进行+=、-=、/=、*=的运算,将运算结果作为执行语句的后值。
68.步骤34):对于自增自减语句的数据流转换函数,根据单目运算符的类型,将前值加一或减一作为执行语句后的值。
69.步骤35):对于循环语句的数据流转换函数,需要对循环体中的语句进行数据流分析,将每一次执行完循环体的后值作为下一次循环的前值,如此执行当前循环的循环上界次。由于本方法是顺序分析所有循环语句,所以当前循环已经经过了循环上界分析,并记录了循环上界结果。
70.步骤36):对于变量在函数内进行初始化的情况,进行过程内的数据流分析。遍历函数体的控制流图,分析语句中是否存在待分析变量,若存在则根据语句类型传入对应的数据流转换函数分析变量后值。
71.步骤37):对于变量来自于形参的情况进行过程间的数据流分析。根据函数调用图,找到当前函数的所有调用者以及函数调用点,根据变量在形参中的位置,匹配函数调用
点的实参。调用步骤3)递归地分析该实参可能的最大值或最小值,并将分析结果传递给形参。再对该变量进行过程内的数据流分析。
72.步骤4):递归分析计算表达式的可能值,其中对于表达式中的普通变量则调用步骤3)的方法分析出具体值。
73.所述步骤4)具体包括以下步骤:
74.步骤41):对于普通变量,调用步骤3)中的方法分析该变量的可能值;
75.步骤42):对于双目运算表达式,若表达式为算术运算,递归调用步骤4)计算表达式左值和右值,根据运算符类型对表达式左值和右值进行相应的加、减、乘、除、取余运算;若表达式为关系运算,递归调用步骤4)计算表达式左值和右值,根据运算符类型对表达式左值和右值进行相应的相等、不等、大于、小于、大于等于、小于等于的关系判断,得到最终结果;
76.步骤43):对于三目运算表达式,形式为cond?x:y,递归调用步骤4)计算条件cond,如果cond的值为true,递归调用步骤4)计算x的值并返回;否则,递归调用步骤4)计算y的值并返回;
77.步骤44):对于函数调用表达式,定位该函数的函数体并遍历函数体的控制流图,得到该函数的返回表达式,递归调用步骤4)计算该表达式的值并返回。
78.步骤5):根据for语句、while语句、do-while语句的语法模式,使用步骤4)的方法分析计算循环上界依赖表达式的可能值。分别针对简单循环、嵌套循环、连锁循环归纳计算循环上界的公式并计算最终结果。
79.所述步骤5)具体包括以下步骤:
80.步骤51):根据for语句、while语句、do-while语句的语法模式,调用步骤4)的方法,分析循环控制变量初始表达式和循环控制变量增量表达式的可能值;
81.步骤52):对于简单循环,根据公式
82.loop_upbound=|end_value-init_value|/increment_value计算出当前循环的循环次数。其中loop_upbound为循环上界结果,end_value为循环控制变量终止值,init_value循环控制变量初始值,increment_value为循环控制变量增量值;
83.步骤53):对于嵌套循环,总迭代次数等于外层循环变量每种取值情况下的内层循环次数的加和。本方法主要考虑内层循环的初始表达式或终止表达式为外层循环控制变量的情况。对于内层循环初始表达式可变的情况,若内层循环递增嵌套循环计算公式为若内层循环递减嵌套循环计算公式为其中i为内层循环初始表达式,out_init为外层循环的初始值,out_end为外层循环的终止值,in_end为内层循环的终止值。对于内层循环终止表达式可变的情况,若内层循环递增,嵌套循环计算公式为若内层循环递减,嵌套循环计算公式为其中i为内层循环终止表达式,in_init为内层循环的初始值;
84.步骤54):对于连锁循环,若各循环之间没有依赖关系,则按照分析简单循环或嵌套循环的方法对各循环语句进行独立分析。若循环之间存在依赖关系,即后续循环上界依赖于前面循环中进行了更新的变量,方法是顺序分析循环语句,记录已分析循环语句的循环上界,即可得到该循环语句的数据流转换函数,具体来说,将每一次执行完循环体的后值作为下一次循环的前值,如此执行当前循环的循环上界次就可以得到循环语句的后值。将该值作为下一个循环依赖变量的前值即可分析下一个循环的循环上界。
85.步骤55):本方法考虑了使用频率较高的基本表达式,对于没有考虑到的表达式状态或者存在变量来自于外部输入而无法计算表达式确定值的情况,则输出表达式字符串以及分析过程中得到的信息。
86.以上所述为本发明的实施例,但此处所描述的具体实施例仅仅用以解释本发明,并不用于限定本发明。凡在不脱离本发明的原理和精神的情况下依本发明申请专利范围所做的任何省略、修改、等同替换等,均应包含在本公开的保护范围之内。