程序分析:保证软件质量的有效方法

2,655 阅读4分钟

程序分析:保证软件质量的有效方法

今天简单的聊一聊软件质量保证中的program analysis 其实发现错误的方法不只有软件测试,还有其他的一些方法。

  1. 检查代码:检查 inspections
  2. 分析代码:代码分析,证明 code analysis, proofs

inspections 一般是人类完成的,而code analysis是使用工具完成的。

Inspection

人类系统的对代码,文档等进行检查。

Inspection team

一般团队由若干程序员和特殊专家组成。团队成员一般是4-6个,甚至更少。组长是一个有丰富经验的项目之外的项目经理。

  1. 简单检查 → 一人
  2. 复杂检查 → 两人
  3. 特殊领域 →三人以上

一般工作流程是准备,检查,通知程序员。

那么检查的依据是什么呢? TO-DO list. 像这样的

我们叫todo list 为checklist。 它是由一系列要检查的具体问题构成,这些问题是客观的,没有二义性,是可以被检查的。

注意表头有一个Level,这代表难度系数。level 1: simple, level 2: complex.

注意 不要觉得人工检查就没什么重要性,大量的例子表明,这是最有效,最有效率的方法。

KLOC: 一千行代码

code analysis

人类适合做的是创新,分析,并不适合做重复,简单的工作,当人也不适合需要管理很多细节的任务。很多问题还是需要借助工具的。

一般分为static analysi 和 dynamic analysis。

Static analysis: 不执行程序,分析代码。

Dynamic analysis: 执行程序。

二者各有利弊,比如static analysis 可能会报出很多假错误(false positive), 而dynamic analysis会局限在某个机器的某个配置环境上。

symbolic execution

symbolix execution 可以用于static analysis(也可以用于dynamic analysis)。它的理念就是,不用变量不是具体的值,而是一个symbol,就像方程中的x。

看下面的程序

int max(int a, int b){
	if(a > b}{
		return a;
	}else{
		return b;
	}
}

这里有一个分支,如果程序中有很多这样的分支,那么就会变得异常复杂,一般解决方法是我们放弃部分准确性。比如:

M = (L + H) /2 ⇒ L ≤ M ≤ H

简而言之就是,使用一个必要条件W, 去替换充分条件P. P=>W

这样做的结果就是,只能用来发现错误,但不能证明程序的正确性。

具体大家感兴趣可以看看KLEE 工具

Dynamic analysis

动态分析就比较有意思了,原理和有限状态机有关。

比如 memory analysis

内存有三种状态,分析工具会记录内存的状态,如果在这个状态做了不该有的行为,那么意味着有错误。比如在分配的内存边界之外的地方设置状态为unallocated,那么在程序访问这里时,就会认为read error.

在比如Data race

data race 就是说两个线程访问同一个位置的,并且有一个要进行写操作 并且没有锁的保护。

对于这个问题,如果使用测试,那测试文件其实很难写的,尤其是情况比较复杂的情况下。那static analysis? 可以,但是可能出错,而且处理这个问题,效率并不高。

这个时候,可以使用的是dynamic analysis.

Lockset discipline: 每一个共享变量必须被锁保护。

比如:

  1. 工具分析到共享变量x有锁集合lockset(X)
  2. 访问X的线程T获得的锁集合locksert(T)
  3. 如果lockset(T) 和lockset(X)没有交集,那么意味着程序出现了data race
  • memory check 和 data race 我在之前就在valgrind工具学习篇讲过了,感兴趣的可以看看这篇的理论怎么在实际valgrind工具应用到的。

总结

今天讲的内容偏理论,而且和编程好像没有什么关系?但是这也是程序员的素养吧,最起码得知道相关的知识,这样以后有问题解决不了了,可以想想,没准这些工具可以帮你发现问题所在的病根。另外面试的时候,你可以说我会使用什么什么工具,它的原理是什么什么。这就从会用工具的人中脱颖而出了。