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

2019-04-23 12:46

分支点依赖于目标结构指令集(看来要好好理解分支的含义,还需要对汇编有一定的了解)。第12行是一个简单的if语句,所以有一个分支点。在这里我们可以注意到这是50%,这通过我们前面观察程序的执行次数可以看出。其他的分支点有一些难于分析。例如,

第7行是一个while语句,有两个分支点。在X86汇编中,这一行编译成我们下面所看到的样子: 1: cmpl $0, -20(?p) 2: jne .L4 3: jmp .L1

从这里我们可看出,swap变量与0进行比较。如果他不等于0,就会跳转到第2行,.L4。否则要跳转到第3行,.L1。第2行所示的分支概率为67%,这是因为这一行执行3次,但是jne只执行了两次。当第2行的jne并没有执行时,我们直接跳转到第3行。这只执行一次,但是一旦执行,程序就结束了。所以分支1要花费100%的时间。

第33行的printf()调用;其下面有一行call 0 returned 100%; 关于这个在手册上是如此解释的:如果一个函数调用至少被执行一次的话,gcov给出的百分比表示“函数返回次数 除以 函数调用次数”, 通常这个数值是100%,但是对于象“exit”或者“longjmp”这类并不是每次调用都返回的函数来说,这个百分比就小于100%。(For a call, if it was executed at least once, then a percentage indicating the number of times the call returned divided by the number of times the call was executed will be printed. This will usually be 100%, but may be less for functions call \

疑惑的地方:这里的分支是如何划分的,一个for怎么有三个分支,并且每个分支都执行到了??是不是“i=0;i<10;i++”认为是3个分支?

关于分支百分比,手册上是这样解释的:如果某个分支从没被执行过,则给出“never executed”;否则gcov给出的百分比说明这个分支“taken的次数”除以“executed的次数”(郁闷这里take如何理解那???)(For a branch, if it was executed at least once, then a percentage indicating the number of times the branch was taken divided by the number of times the branch was executed will be printed. Otherwise, the message ``never executed'' is printed.)。

所以分支概率在理解程序流时是相当有用的,但是要参考汇编代码,需要理解分支点在哪里。 看起来有点晕?

? 不完整程序测试

当gcov计数一个测试并不是100%的程序时,并没有执行的行是标记为####,而不是执行次数。下面显示的是一个由gcov创建的文件来显示少于100%的测试。 1: #include 2: 3: int main() 4: 1 { 5: 1 int a=1, b=2; 6: 7: 1 if (a == 1) {

8: 1 printf(\ 9: } else { 10: ###### printf(\ 11: } 12: 13: 1 if (b == 1) { 14: ###### printf(\ 15: } else { 16: 1 printf(\ 17: } 18: 19: 1 return 0; 20: }

当这个程序运行时,gcov也会向标准输出输出相应的信息。他会显示可能执行的源码行的行数以及实际运行的百分比。

$ gcov incomptest.c 77.78% of 9 source lines executed in file incomptest.c Creating incomptest.c.gcov. $ 如果我们的例子程序有多个函数,我们可以通过使用-f选项来查看每一个函数的执行情况。如下面的我们以bubbleSort程序所进行的演示:

$ gcov -f bubblesort.c 100.00% of 11 source lines executed in function bubbleSort 100.00% of 6 source lines executed in function main 100.00% of 17 source lines executed in file bubblesort.c Creating bubblesort.c.gcov. $ ? gcov可用的选项

gcov程序调用的格式为: gcov [options] sourcefile 其可用的选项如下:

选项 目的

-v,-version 打印版本信息 -h,-help 打印帮助信息

-b,-branch-probabilities 向输出文件输出分支频度 -c,-branch-counts 打印分支计数而不是分支频度 -n,-no-output 不创建gcov输出文件 -l,-long-file-names 创建长文件名

-f,-function-summaries 打印每一个函数的概要 -o,-object-directory .bb,.bbg,.da文件存放的目录

从上面这个表中,我们可以看到一个单个字符选项,以及一个长选项。当从命令行中使用gcov命令时短选项是比较有用的,但是当gcov是Makefile的一个部分时,应使用长选项,因为这更易于理解。 当了解gcov程序的版本信息时,可以使用-v选项。因为gcov是与一个指定的编译器工具链联系在一起的(实际上是由gcc工具链而构建的),gcc版本与gcov的版本是相同的。gcov程序的简介以及选项帮助可以用-h选项来进行显示。

在你的目录下多了几个文件,后缀是.gcda,gcno,呵呵,恭喜你,你的gcov的版本还是比较新的,在以前旧一点的版本中,有.bb,.bbg这种后缀(我pc上安装的是2.4.18-14的内核,生成了以这个为扩展名的文件),不过现在都没了,其实gcov跑的数据统计什么的都保存在这些文件中,这就是为什么,你可以多次跑程序,而gcov会自己统计的神奇本领所在。

另外在man gcov中还提到,gprof可以使用gcov生成的日志文件进一步分析性能,原文如下:gcov creates a logfile called sourcefile.gcov which indicates how many times each line of a source file sourcefile.c has executed. You can use these logfiles along with gprof to aid in fine-tuning the performance of your programs. gprof gives timing information you can use along with the information you get from gcov.

gcov [-b] [-c] [-v] [-n] [-l] [-f] [-o directory] sourcefile -b

Write branch frequencies to the output file, and write branch summary info to the standard output. This option allows you to see how often each branch in your program was taken.

//b(ranch),分支测试 -c

Write branch frequencies as the number of branches taken, rather than the percentage of branches taken. -v

Display the gcov version number (on the standard error stream). -n

Do not create the gcov output file. -l

Create long file names for included source files. For example, if the header file `x.h' contains code, and was included in the file `a.c', then running gcov on the file `a.c' will produce an output file called `a.c.x.h.gcov' instead of `x.h.gcov'. This can be useful if `x.h' is included in multiple source files.

-f

Output summaries for each function in addition to the file level summary. -o

The directory where the object files live. Gcov will search for `.bb', `.bbg', and `.da' files in this directory. //新版的是这么说的 -o directory│file

--object-directory directory --object-file file

Specify either the directory containing the gcov data files, or the object path name. The .gcno, and .gcda data files are searched for using this option. If a directory is specified, the data files are in that directory and named after the source file name, without its extension. If a file is specified here, the data files are named after that file, without its extension. If this option is not sup- plied, it defaults to the current directory.

其他的还有新版的-u, -u

--unconditional-branches

When branch counts are given, include those of unconditional branches. Unconditional branches are normally not interesting. -p

--preserve-paths

Preserve complete path information in the names of generated .gcov files. Without this option, just the filename component is used. With this option, all directories are used, with ’/’ characters

translated to ’#’ characters, ’.’ directory components removed and ’..’ components renamed to ’^’. This is useful if sourcefiles are in several different directories. It also affects the -l option.

man一下就能看到,我也不多说了

? Using gcov with GCC Optimization

If you plan to use gcov to help optimize your code, you must first com- pile your program with two special GCC options: -fprofile-arcs

-ftest-coverage. Aside from that, you can use any other GCC options; but if you want to prove that every single line in your program was executed, you should not compile with optimization at the same time. On some machines the optimizer can eliminate some simple code lines by combining them with other lines. For example, code like this:

if (a != b) c = 1; else c = 0;

can be compiled into one instruction on some machines. In this case, there is no way for gcov to calculate separate execution counts for each line because there isn't separate code for each line. Hence the gcov output looks like this if you compiled the program with optimiza- tion:

100 if (a != b) 100 c = 1; 100 else 100 c = 0;

The output shows that this block of code, combined by optimization, executed 100 times. In one sense this result is correct, because there was only one instruction representing all four of these lines. How- ever, the output does not indicate how many times the result was 0 and how many times the result was 1.

5.2 使用gprof来优化你的C/C++程序

作者:arnouten(Q)bzzt.net linuxfocus (2005-05-18 15:03:24) 中文编译: 小 汪

谨记:在值得优化的地方优化!没有必要花几个小时来优化一段实际上只运行0.04秒的程序。

gprof是GNU profiler工具。可以显示程序运行的“flat profile”,包括每个函数的调用次数,每个函数消耗的处理器时间。也可以显示“调用图”,包括函数的调用关系,每个函数调用花费了多少时间。还可以显示“注释的源代码”,是程序源代码的一个复本,标记有程序中每行代码的执行次数。

gprof 使用了一种异常简单但是非常有效的方法来优化C/C++ 程序,而且能很容易的识别出值得优化的代码。一个简单的案例分析将会显示,GProf如何通过识别并优化两个关键的数据结构,将实际应用中的程序从3分钟的运行时优化到5秒的。

? 获得gprof

在gprof这个工具之前,当前首先要获得这个工具,gporf是gnu/gcc工具集中的一个工具,但是按照论坛上的说法,通常在生成工具集时,这个工具默认是不产生的,需要修改配置文件才能获得。

关于这个论坛上面的讨论是:


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

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

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

马上注册会员

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