嵌入式linux应用程序调试方法(6)

2019-04-23 12:46

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 2: 3: void bubbleSort( int list[], int size ) 4: { 5: int i, j, temp, swap = 1; 6: 7: while (swap) { 8: 9: swap = 0; 10: 11: for ( i = (size-1) ; i >= 0 ; i— ) { 12: 13: for ( j = 1 ; j <= i ; j++ ) { 14: 15: if ( list[j-1] > list[j] ) { 16: 17: temp = list[j-1]; 18: list[j-1] = list[j]; 19: list[j] = temp; 20: swap = 1; 21: 22: } 23: 24: } 25: 26: } 27:

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:}

第一列显示了源码中每一行源码所执行的次数。在一些情况下,执行次数并没有提供,因为他们是并不会影响代码的简单C源码元素。

这些计数可以提供一些关于程序执行的信息。例如,第12行执行了90次,而14-17行的代码只是执行了45次。这告诉我们当这个函数调用了90次,真正成功的仅是45次。换句话说,大部分的测试时间浪费在两个元素的交换上。这是由于测试数据的顺序所造成的。

从这里我们可以看到代码段中最常执行的部分就是排序算法的内循环部分。这是因为由于退出测试第10行要比第12行执行的次数多一些。

遗憾的是:我使用arm交叉编译环境按照上面的步骤编译程序,下载到目标板上运行时程序可以正常执行;但是没有日志文件产生;提示为“profiling:/home/zpf/gdb_test/bubblesort.gcda:Cannot open”;“/home/zpf/gdb_test/”是我在linux服务器上编译bubblesort的目录;从这里看,要想利用gcov进行覆盖测试的话,必须在你编译的那个目录执行,看来nfs是嵌入式调试的根本???

? 查看分支效率

使用-b选项可以查看程序的分支效率。这个选项会输出程序中每一个分支的频度与相应的摘要。例如,我们使用-b选项来执行gcov命令:

$ gcov -b bubblesort.c 100.00% of 17 source lines executed in file bubblesort.c 100.00% of 12 branches executed in file bubblesort.c 100.00% of 12 branches taken at least once in file bubblesort.c 100.00% of 2 calls 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) function bubbleSort called 1 returned 100% blocks executed 100% 1: 3:{ 1: 4: int i,j,temp,swap=1; 4: 5: while(swap) branch 0 taken 67% branch 1 taken 33% (fallthrough) -: 6: { 2: 7: swap=0;

22: 8: for(i=(size-1);i>=0;i--) branch 0 taken 91%

branch 1 taken 9% (fallthrough) -: 9: {

110: 10: for(j=1;j<=i;j++) branch 0 taken 82%

branch 1 taken 18% (fallthrough) -: 11: {

90: 12: if(list[j-1]>list[j]) branch 0 taken 50% (fallthrough) branch 1 taken 50% -: 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()

function main called 1 returned 100% blocks executed 100% 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); call 0 returned 100% -: 29:

-: 30: /*print out the final list*/ 11: 31: for(i=0;i<10;i++) branch 0 taken = 91% branch 1 taken = 100% branch 2 taken = 100% -: 32: {

10: 33: printf(\call 0 returned 100% -: 34: }

1: 35: return 0; -: 36:}

与前一个的文件类似,但是这一次每一个分支点都用他们的频度进行了标示。


嵌入式linux应用程序调试方法(6).doc 将本文的Word文档下载到电脑 下载失败或者文档不完整,请联系客服人员解决!

下一篇:测试技术课后答案全集—第三版

相关阅读
本类排行
× 注册会员免费下载(下载后可以自由复制和排版)

马上注册会员

注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信: QQ: