查找嵌入式C语言程序/软件中的缺陷的多种技术(2)

时间:2010-10-15

     在单元测试中使用运行时内存监测:我们使用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++test的BugDetective来进行数据流分析,BugDetective能模拟系统中的不同路径并检查这些路径中是否存在潜在的问题。进行数据流分析后,我们得到如下结果:


  仔细分析的结果,我们发现程序中存在一条未被覆盖到的潜在路径可能会造成在finalize()函数中出现两次free的操作。在程序中,reportSensorValue()函数调用了finalize()函数,然后finalize()函数调用了free()。同时,finalize()函数还会被mainLoop()函数调用。我们可以修改finalize()函数以使其更加智能化,从而修复这个问题,修改后的代码如下:

  void finalize()

  {

  if (messages) {

  free(messages[0]);

  free(messages[1]);

  free(messages[2]);

  free(messages);

  messages = 0;

  }

  }

  现在我们再次运行数据流分析,得到的结果将只有两个问题:


  这里我们可能使用了-1作为索引来访问了数组。这是由于整型变量index被设置的初始值为-1,并且存在一条可能通过if语句的路径在未将该整型变量正确的进行初始化之前便调用了printMessage()函数。运行时分析未检查到这样的一条路径,并且该路径很有可能在真实世界中永远不可能被执行到。这就是静态数据流分析相对于运真实运行时内存监测主要的不足:数据流分析能检查出潜在的路径,这些路径可能包含在程序实际执行过程中不会执行到或不存在的路径。尽管如此,为了做到有备无患,我们删除了上述的不必要的条件(value>=0)以修改这个潜在的错误。

  void handleSensorValue(int value)

  {

  initialize();

  int index = -1;

  if (value <= 10) {

  index = VALUE_LOW;

  } else {

  index = VALUE_HIGH;

  }

  printMessage(index, value);

  }

  相同地,我们也对一个的错误进行相应的处理。现在我们再次运行数据流分析,将不会再有错误被出来。


  
上一篇:查找嵌入式C语言程序/软件中的缺陷的多种技术(1)
下一篇:查找嵌入式C语言程序/软件中的缺陷的多种技术(3)

免责声明: 凡注明来源本网的所有作品,均为本网合法拥有版权或有权使用的作品,欢迎转载,注明出处。非本网作品均来自互联网,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责。

相关技术资料