1.程序分析技术概述
编程是大学阶段必须掌握的生存能力,过程式语言到面向对象技术的c++,到java语言。Java语言最早是为电子产品创建的新语言,因此可移植性好,不需要对内存进行干涉,因此没有指针的功能。面向对象技术经过C++语言的多线程多核的发展后,在hadoop和noSQL的数据分析技术成为最近几年云计算的支持技术的IT界,开始有些逊色于函数式语言、R语言和Python。
一个好的程序员在计算机软件界,不仅脚踏实地掌握高超的编程能力,在工作实践中应用数据结构实现高质量程序和选择好的算法提高程序效率,在项目开发的软件工程中对总体设计、详细设计和软件测试能熟练掌握和应用,而且有必要掌握程序分析技术。
在编译技术、程序调试、程序测试和并行程序设计的范围中,程序分析技术包括对源程序进行程序路径、循环语句分析方法,以及变量的数据流和程序的控制流分析方法。程序路径分析有静态路径分析和动态路径分析,应用编译技术的DAG图和CFG图;而循环语句分析有循环语句执行次数和循环终止条件分析。数据流和控制流根据du链和ud链可发现数据依赖。主循环展开也属于编译技术。
程序切片因关注一个问题而产生,例如发现一个变量的错误位置,在语句级分析的层次上。依靠程序点n的相关语句间的控制依赖和变量间的数据依赖,而且更关注语句控制依赖的相关度,类似软件工程的控制内聚和数据内聚。设置程序点n,要求它的相关语句与其它兴趣点控制范围相对无关。切片标准(slicing criterion)是程序点n的变量值,类似希尔排序,而软件工程的功能内聚则像快速排序。程序切片技术常用在程序调试和程序测试。在并行程序设计中,可应用程序分析和程序切片技术,将程序合理地分成并行计算程序块,根据数据相关性完成数据分配。掌握数据相关性和数据依赖,对hadoop编程有帮助。
实际上,程序分析技术并不陌生,程序流程图和发现语句错误的debug都是程序分析技术。程序分析技术的应用和为了进一步发展而掌握的技术有很多,例如源程序的功能主题发现,用到编辑距离,在互联网文件中应用广泛;在面向对象技术中,应掌握语义操作和构件,属于软件工程的功能内聚,是软件复用的基础;部分求值技术是输入数据驱动的程序分析方法,可在软件测试中应用,而且在程序运行时间上能根据不同输入数据的执行时间,分析程序的运行时间和时间复杂度;基本块传递函数尽管是编译技术,但是对程序功能和变量的数据分析有用。
因此,程序分析技术是IT界程序员应该掌握的技术,即使有些困难,但是应用在实践中,收获将有很多。下面将用4~5篇文章介绍给大家。
2.程序路径分析
程序路径是程序的第一个语句到生成数据输出的所谓“出口”的语句序列。现代高级语言的结构程序有多个出口,这是控制语句决定。程序有多条路径,这是控制语句和循环语句决定的。分析程序路径的例题。
2.1 数据分析
eg1.取三个数x1,x2,x3的中间数
double GetMid(double x1, double x2, double x3)
{
double mid=x3;
if(x2<x3){ //1个if语句
if(x1<x2) //第二个if语句
mid=x2;
else{ //第二个if语句的else语句,从{}可知。
if(x1<x3) //第三个if语句
mid=x1;
}
}else //第一个if语句的else语句
if(x1>x2) //第四个if语句
mid=x2;
else //第四个if语句的else语句
, if(x1>x3) //第五个if语句
mid=x1;
return mid;
}
程序阅读是掌握程序功能的方法,数据分析技术可准确分析例题1的功能。数据分析技术首先看输出。return mid返回的mid,则是程序的输出数据。因此,将mid作为一列。其次看输入数据,函数GetMid的参数有x1,x2,x3,则都作为一列。根据第一个语句mid=x3,则有
x1 x2 x3 mid
x3
而根据第一到第五个if语句,有
mid x1 x2 x3
x3 B1(第一个语句记为B1)
x2<x3 if1(第一个if语句)
x2 x1<x2 if2(第二个if语句)
第一个程序路径B1->if1->if2
x1 (x1>x2) else2(第二个if语句的else语句)
x1<x3 if3(第三个if语句)
第二个程序路径B1->if1->else2->if3
(x2>x3) else1(第一个if语句的else语句)
x2 x1>x2 if4(第四个if语句)
第三个程序路径B1->else1->if4
(x1<x2) else4(第四个if语句的else语句)
x1 x1>x3 if5(第五个if语句)
第四个程序路径B1->else1->else4->if5
第五个程序路径B1.
在以上分析可知,在三个数中取中间数程序有5个路径。
2.2 程序路径静态分析
对GetMid()的每一个语句进行了层次标注,而多个相邻赋值语句则标注为语句块B。程序的输入数据集合用{x1,x2,x3}表示。对每个if语句的输入数据集合,则在注释中表示。
eg1.1 取三个数的中间数
double GetMid(double x1, double x2, double x3)
{
double mid=x3;//B1
if(x2<x3){// if1 {x1,(x2,x3)}={<x1,x2,x3>,< x2, x1, x3>,< x2, x3, x1>}
if(x1<x2)// if2划分等价类<x1,x2,x3>
mid=x2; //path1:< x1, x2, x3>
else{// else2 {< x2, x1, x3>,< x2, x3, x1>}
if(x1<x3)// if3划分等价类<x2,x1,x3>
mid=x1; //path2:< x2, x1, x3>
}
}else // else1 {x1,(x3,x2)}={ < x1, x3, x2>,< x3, x1, x2>,< x3, x2, x1>}
if(x1>x2)// if21
mid=x2; //path3:< x3, x2, x1>
else // else21 { < x1, x3, x2>,< x3, x1, x2>}
, if(x1>x3)// if31
mid=x1;// path4:< x3, x1, x2>
return mid; //L_OUT[if_elseB]
// path5=[x3]<R>,mid=x3
}
程序的数据集合分析:
L_IN[B1]= A={ x1, x2, x3}
L_OUT[B1]={A} //mid=x3
L_IN[if1]={ x1, x2, x3}
L_OUT[if1]=(x2, x3) //(x2, x3)是有序集
L_IN[if2]={< x1, x2, x3>,< x2, x1, x3>,< x2, x3, x1>}
L_OUT[if2]=< x1, x2, x3> //path1=< x1, x2, x3>,mid=x2
L_IN[else2]={< x2, x1, x3>,< x2, x3, x1>}=L_OUT[else2]≠L_OUT[if2]
L_IN[if3]= L_IN[else2]={< x2, x1, x3>,< x2, x3, x1>}
L_OUT[if3]= < x2, x1, x3> //path2=< x2, x1, x3>,mid=x1
L_IN[else1]=( x3, x2)= L_OUT[else1]
L_IN[if21]= {< x1, x3, x2>,< x3, x1, x2>,< x3, x2, x1>}
L_OUT[if21]= < x3, x2, x1> //path3=< x3, x2, x1>,mid=x2
L_IN[else21]= {< x1, x3, x2>,< x3, x1, x2>}
L_IN[if31]= L_OUT[else21]= {< x1, x3, x2>,< x3, x1, x2>}
L_OUT[if31]= < x3, x1, x2> //path4=< x3, x1, x2>,mid=x1
L_OUT[if_elseB]={ < x1, x3, x2>,< x2, x3, x1>} //path5=[x3]<R>,mid=x3
则parA={< x1, x2, x3>,< x2, x1, x3>,< x3, x2, x1>,< x3, x1, x2>,[x3]<R>}.因为parA=A,所以程序正确。
if_elseB并不是真实存在的语句,是第一层if语句的else条件语句块。