当前位置:首页 > 嵌入式linux应用程序调试方法
C/C++代码覆盖、性能profiling工具一般基于GNU的gprof和gcov。还有一类基于模拟器的profiling工具,如IBM Purify, Valgrind。KCahcegrind是Callgrind,OProfile等的GUI前端。性能测试工具有ggcof,kprof,lcov等等。lcov是Linux Testing Project工具之一,见http://ltp.sourceforge.net/tooltable.php上的工具列表。这儿还有压力测试、WEB Server测试等许多工具。在http://www.testingfaqs.org分类归纳了多种软件测试工具。
5.1 用gcov来测试代码覆盖率
gcov是gnu/gcc工具库中的一个组件, 用来测试代码的覆盖率;当构建一个程序时,gcov会监视一个程序的执行,并且会标识出执行了哪一行源码,哪一行没有执行。更进一步,gcov可以标识出某一行源执行的次数,这样就可以知道程序在哪里花费了大多数的时间。
为什么要测试代码覆盖率?
我是不喜欢在代码中有跑不到的地方,那只是在白白浪费空间,降低效率
当然了,有些时候,我们可以通过跑代码覆盖率来发现我们有什么异常情况没有进行测试,毕竟单元测试的用例,不可能一下就想的很全面的。
例如,你的程序在某个函数的入口前处检测了指针不为空,你进入调用函数以后又检测了一回这个指针,并且对为NULL的情况进行处理,那么两处之中必有一处是在浪费空间,当然你的硬盘大,放的下,但是代码写的精致一些,不是更好么?
? 获得gcov
gcov是gnu/gcc工具库的组件,所以在建立交叉编译工具的时候需要指定创建这个工具。
在arm-linux-的交叉编译工具中,arm-linux-gcov好像默认是存在的;操作系统组给我的交叉编译环境中是有这一工具的;但是uClinux的交叉编译环境中默认好像是没有这个工具的;具体的搭建从下面gprof的讨论也许能够得到一些信息。因为现在我还没有移植操作系统的经验,所以无法对这个进行证实。
关于这个论坛上面的讨论是:
> The gprof program, for historical reasons, is sometimes excluded > from a cross-targeted toolchain. If you have a source tree with > a Cygnus configure script at the top level, or a gcc source tree, > then look for the \
> configure.in, remove \ Then reconfigure the build tree, > and run \
That did it!
Just to be clear, this is what I did:
I untar'd the binutils-2.12.1 tar ball and edited
binutils-2.12.1/configure.in. There's a line containing \ several packages (like gprof, sed,...); I removed gprof from that list.
I then followed the instructions here for building binutils:
http://sources.redhat.com/ecos/tools/linux-arm-elf.html
and arm-elf-gprof was created! Score!
? 使用gcov
使用gcov很简单, 首先在编译的时候加上-fprofile-arcs -ftest-coverage,同时链接的时候也加上这些选项;需要特别说明的时,gcov要求被测试程序在执行的时能够访问到它编译的那个目录,因为要使用到编译过程中生成的一个文件(我测试的时是这样的,执行时提示找不到/home/zpf/gdb_test/bubblesort.gcda这个文件,而我得bubblesort程序是在/home/zpf/gdb_tes/这个目录里编译的);所以如果是嵌入式的话,就需要nfs这样的工具支持。
? 示例程序源代码
例如我们需要测试以下bubblesort的代码: 1: #include
28: } 29: 30: } 31: 32: int main() 33: { 34: int theList[10]={10, 9, 8, 7, 6, 5, 4, 3, 2, 1}; 35: int i; 36: 37: /* Invoke the bubble sort algorithm */ 38: bubbleSort( theList, 10 ); 39: 40: /* Print out the final list */ 41: for (i = 0 ; i < 10 ; i++) { 42: printf(\43: } 44: 45: }
? 编译程序
如果要使用gcov进行覆盖测试,在编译程序时,必须加-fprofile-arcs -ftest-coverage编译选项;下面是我们用来演示编译bubbleSort.c的命令:
gcc bubblesort.c -o bubblesort -ftest-coverage -fprofile-arcs
当我们执行生成的bubblesort程序时会生成一些包含关于程序的相关数据的文件。gcov程序将会使用这些文件来报告数据并且向开发者提供相应的信息。当指定“-ftest-coverage”(注意这是一个选项而不是两个选项)选项时会为每一个源码生成两个文件,他们以“.bb”与“.bbg”为扩展名,并且用这些文件来重组每一个可执行程序的程序流图。当指定“-fprofile-arcs” (注意这是一个选项而不是两个选项),将会生成一个包含每一个指令分支的执行计数的以“.da”为扩展名的文件。这些文件会在执行以后与源码文件一起使用,来标识源码的执行行为。
? 运行程序
运行刚才编译生成的bubblesort程序就会生成我们在前面所讨论的那些附带文件。然后我们使用我们希望进行检测的源码运行gcov程序。如下面所示: $ ./bubblesort ... $ gcov bubblesort.c 100.00% of 17 source lines executed in file bubblesort.c Creating bubblesort.c.gcov. 以上信息告诉我们,在这个例子程序中所有的源码行至少都执行了一次。另外还可以通过查看生成的bubblesort.c.gcov文件来了解每一源码行所实际运行的次数。如下面所示:
-: 0:Source:bubblesort.c -: 0:Graph:bubblesort.gcno -: 0:Data:bubblesort.gcda -: 0:Runs:1 -: 0:Programs:1
-: 1:#include
-: 2:void bubbleSort(int list[],int size) 1: 3:{
1: 4: int i,j,temp,swap=1; 4: 5: while(swap) -: 6: {
2: 7: swap=0;
22: 8: for(i=(size-1);i>=0;i--) -: 9: {
110: 10: for(j=1;j<=i;j++) -: 11: {
90: 12: if(list[j-1]>list[j]) -: 13: {
45: 14: temp=list[j-1]; 45: 15: list[j-1]=list[j]; 45: 16: list[j]=temp; 45: 17: swap=1; -: 18: } -: 19: } -: 20: } -: 21: } 1: 22:}
-: 23:int main() 1: 24:{
1: 25: int theList[10]={10,9,8,7,6,5,4,3,2,1}; -: 26: int i;
-: 27: /*Invoke the buble sort algorithm*/ 1: 28: bubbleSort(theList,10); -: 29:
-: 30: /*print out the final list*/ 11: 31: for(i=0;i<10;i++) -: 32: {
10: 33: printf(\ -: 34: }
1: 35: return 0; -: 36:}
共分享92篇相关文档