关于一个程序错误的归零想到的
最近参加了一个关于程序编码错误引起系统故障的归零会议评审,系统的故障现象为系统运行中会反映出某仪表在显示中偶尔出现跳变的情况,经查证是某DSP程序中排序函数C语言指针使用超限导致的。故障的代码段类似于这样的一种形式:
//A函数
void sequence(int arr[], int len){
int i,j,temp;
for (i=1;i<=len;i++){
temp = arr[i];
for (j=i;j>0 && arr[j-1]>temp;j--)
arr[j] = arr[j-1];
arr[j] = temp;
}
}
//B函数
int calculate(int a1,int a2) //这个函数调用上边的函数
{
//这里有一些代码,生成了一个int a[5]
//这里有调用sequence(),对a[5]进行排序
sequence(a,5); //这一句发生了错误,这里应该是4,
// 其他的一些处理
}
挺简单的一个错误,也应该是很常见的错误,但在企业的内部单元测试、配置项测试、系统测试中居然都没有测出来(集成测试在体系中被裁剪掉了),一直到联调的时候才被发现。因为涉及到故障归零,所以肯定要分析原因,看看板子打到哪里合适,然后在制定整改措施。
本来在我的考虑中,这个问题应该会打在单元测试不充分上,照理说,语句覆盖100%的单元测试,应该能测到很明显的问题。但仔细分析了一下,还真不能把问题归结给单元测试。
- A函数进行单元测试是没问题的,代码是对的。
- B函数在进行单元测试时,sequence的调用一般是进行打桩处理的,所以B函数也是能通过单元测试的。
把板子打在配置项测试或系统测试?也不太合理,因为B函数也比较低层,配置项和系统测试是根据业务场景设计的测试用例,不容易识别出隐藏很深的数据边界。
个人感觉这个错误,即使是进行人工走查,也不容易看出来,因为在调用时,5个数的排序也会下意识的写5,特别是如果A、B函数写在不同的位置,那么审查到B的时候很可能忘了A的实现细节了。
这个错误属于典型的接口错误,或许可以在集成测试的过程中暴漏,但也是仅仅具备一定的可能性,毕竟集成和集成测试本身不会做的很细。而且大部分组织可能在非关键软件中把集成和集成测试过程裁剪掉了。
我觉得在联试期间能发现这个错误,应该还是比较幸运的,毕竟这种指针问题,到底会导致什么不可知的错误,是非常难预测的,也可能会隐藏的很隐秘,直到关键的时候再爆发出来。