- 易迪拓培训,专注于微波、射频、天线设计工程师的培养
查找嵌入式C语言程序/软件中的缺陷的多种技术
该结果指出在第48行代码处产生了一次读取数组越界的错误。显然,msgIndex变量的值肯定超过了数组的范围。如果我们随着堆栈追踪上一级的原因,我们将发现此处的打印信息所指示的值的确超出了数组的范围(因为在调用printMessage()函数前我们给出了一个错误的条件)。我们可以删除掉这个不必要的条件(value <= 20)以修改这个错误。
void handleSensorValue(int value)
{
initialize();
int index = -1;
if (value >= 0 && value <= 10) {
index = VALUE_LOW;
} else if ((value > 10) && (value <= 20)) {
index = VALUE_HIGH;
}
printMessage(index, value);
}
然后我们重新运行程序,将不会再报告任何内存错误。当我们把程序上载到目标板上时,它似乎如我们预期那么在工作了。尽管如此,我们仍然有一些担心。
我们仅查找到我们所执行的代码路径中的一个内存写溢出实例,我们凭什么能够断定我们尚未执行到的代码就不会有内存写溢出错误了呢?如果我们检查覆盖率分析,我们就会发现reportSensorFailure()这个函数从未被执行到。我们有必要对这个函数进行测试,但是具体如何进行呢?建立一个调用该函数的单元测试用例就是一个不错的办法。
在单元测试中使用运行时内存监测:我们使用C++test的测试用例向导来创建一个测试用例的框架,并向其中添加一些测试代码。然后运行该测试用例——以检查上面提到的未经测试的函数,同时打开运行时内存监测功能。使用C++teST,全过程大约只需要数秒钟。
结果标明该函数已经被覆盖到了,但同时也查找到了新的错误:
我们的测试用例查找到了更多的内存相关错误。很显然,当失败处理函数被调用时,我们的内存初始化存在问题(空指针)。通过更进一步的分析,我们发现在reportSensorValue()函数中存在函数调用顺序错误。
finalize()函数先于printMessage()函数被调用,但是finalize()函数中释放了printMessage()函数需要使用的内存。
void finalize()
{
if (messages) {
free(messages[0]);
free(messages[1]);
free(messages[2]);
}
free(messages);
}
将函数调用顺序进行修改后,我们重新运行程序。
这样我们就解决了上面报告中的第一个错误。现在我们再来分析报告中的第二个错误:即打印信息中的AccessViolatiONException。产生这个错误的原因是相应的消息列表未经初始化。为了解决该问题,我们在打印该信息前调用一次initialize()函数来对其进行初始化。经修改后的函数如下所示:
void reportSensorFailure()
{
initialize();
printMessage(ERROR, 0);
finalize();
}
当我们再次运行该测试用例时,仅有一个任务被报告出来:未经验证的单元测试用例(an unvalidated unit test case),这其实并不算一条错误。我们只需对输出进行一下验证,以将该测试用例转换为回归测试。通过创建合适的断言,C++test会自动为我们完成这些步骤。
来源:中电网
上一篇:浅谈μC/OS任务调度算法的硬件实现
下一篇:基于ARM的高效C语言编程