Linux gcov命令介绍
gcov命令是GNU Code Coverage,它是一个用来分析程序源代码的覆盖率的工具,可以帮助开发者找出程序中未被测试到的代码,提高代码的质量和可靠性。gcov命令可以显示每个源文件的总体覆盖率,以及每个函数和每行代码的覆盖率,还可以生成注释的源代码文件,显示每行代码被执行的次数。
Linux gcov命令适用的Linux版本
gcov命令是GNU编译器集合(GCC)的一部分,因此,只要安装了GCC,就可以使用gcov命令。GCC是Linux系统中最常用的编译器,大多数Linux发行版都自带了GCC,或者可以通过包管理器来安装GCC。例如,在CentOS 7中,可以使用以下命令来安装GCC:
[linux@bashcommandnotfound.cn ~]$ sudo yum install gcc
在CentOS 8中,可以使用以下命令来安装GCC:
[linux@bashcommandnotfound.cn ~]$ sudo dnf install gcc
Linux gcov命令的基本语法
gcov命令的基本语法格式如下:
gcov [选项] 源文件
其中,源文件是要分析的程序的源代码文件,必须是C、C++或Objective-C语言编写的。如果源文件没有指定扩展名,gcov命令会自动添加.c、.cc、.C、.cpp、.cp或.m扩展名。如果源文件有多个扩展名,gcov命令会按照上述顺序查找。
Linux gcov命令的常用选项或参数说明
gcov命令有很多选项或参数,可以用来控制分析的方式和输出的格式。以下是一些常用的选项或参数:
选项或参数 | 说明 |
---|---|
-a | 显示所有函数的覆盖率信息,而不仅仅是主程序中调用的函数 |
-b | 显示分支覆盖率信息,即每个条件语句的真假分支是否被执行 |
-c | 显示调用图覆盖率信息,即每个函数被调用的次数和调用者 |
-f | 显示每个函数的覆盖率信息,包括函数名、行号、执行次数和覆盖百分比 |
-l | 显示每行代码的覆盖率信息,包括行号、执行次数和源代码 |
-n | 不生成注释的源代码文件,只显示覆盖率信息 |
-o <目录> | 指定目标文件(即编译后的可执行文件)的目录,如果不指定,gcov命令会在当前目录或源文件所在的目录中查找 |
-p | 在输出的文件名中保留源文件的路径信息,而不是只显示文件名 |
-r | 删除辅助文件,即.gcda和.gcno文件,这些文件是编译时和运行时生成的,用来存储覆盖率数据 |
-s <目录> | 指定源文件的目录,如果不指定,gcov命令会在当前目录或目标文件所在的目录中查找 |
-u | 不显示未执行的函数和行的覆盖率信息 |
Linux gcov命令的实例
以下是一些使用gcov命令的实例,假设有一个名为hello.c的源文件,内容如下:
#include <stdio.h>
int foo(int x) {
if (x > 0) {
return x + 1;
} else {
return x - 1;
}
}
int main() {
printf("Hello, world!\n");
printf("foo(10) = %d\n", foo(10));
printf("foo(-10) = %d\n", foo(-10));
return 0;
}
实例1:编译源文件并运行程序
为了使用gcov命令,需要在编译源文件时加上-g和-fprofile-arcs -ftest-coverage选项,这样可以生成目标文件、可执行文件和辅助文件。然后运行程序,这样可以收集覆盖率数据。例如:
[linux@bashcommandnotfound.cn ~]$ gcc -g -fprofile-arcs -ftest-coverage hello.c -o hello
[linux@bashcommandnotfound.cn ~]$ ./hello
Hello, world!
foo(10) = 11
foo(-10) = -11
实例2:显示总体覆盖率信息
使用gcov命令不带任何选项,可以显示源文件的总体覆盖率信息,包括文件名、行数、执行次数和覆盖百分比。例如:
[linux@bashcommandnotfound.cn ~]$ gcov hello.c
File 'hello.c'
Lines executed:100.00% of 9
Creating 'hello.c.gcov'
这里可以看到,源文件的总体覆盖率是100%,即所有的代码行都被执行了。同时,gcov命令还生成了一个名为hello.c.gcov的文件,这是一个注释的源代码文件,可以用文本编辑器打开查看。
实例3:显示每个函数的覆盖率信息
使用gcov命令带上-f选项,可以显示每个函数的覆盖率信息,包括函数名、行号、执行次数和覆盖百分比。例如:
[linux@bashcommandnotfound.cn ~]$ gcov -f hello.c
File 'hello.c'
Lines executed:100.00% of 9
Creating 'hello.c.gcov'
Function 'foo'
Lines executed:100.00% of 5
Called 2 times
Function 'main'
Lines executed:100.00% of 4
Called 1 times
这里可以看到,源文件中有两个函数,foo和main,它们的覆盖率都是100%,即所有的函数体内的代码行都被执行了。同时,还可以看到,foo函数被调用了两次,main函数被调用了一次。
实例4:显示分支覆盖率信息
使用gcov命令带上-b选项,可以显示分支覆盖率信息,即每个条件语句的真假分支是否被执行。例如:
[linux@bashcommandnotfound.cn ~]$ gcov -b hello.c
File 'hello.c'
Lines executed:100.00% of 9
Branches executed:100.00% of 4
Taken at least once:100.00% of 4
Calls executed:100.00% of 4
Creating 'hello.c.gcov'
这里可以看到,源文件中有四个分支,它们的覆盖率都是100%,即每个分支都被执行了至少一次。同时,还可以看到,源文件中有四个函数调用,它们的覆盖率也都是100%,即每个函数调用都被执行了。
实例5:显示每行代码的覆盖率信息
使用gcov命令带上-l选项,可以显示每行代码的覆盖率信息,包括行号、执行次数和源代码。例如:
[linux@bashcommandnotfound.cn ~]$ gcov -l hello.c
File 'hello.c'
Lines executed:100.00% of 9
Creating 'hello.c.gcov'
-: 0:Source:hello.c
-: 0:Graph:hello.gcno
-: 0:Data:hello.gcda
-: 0:Runs:
好的,我继续给你显示每行代码的覆盖率信息,包括行号、执行次数和源代码。例如:
```bash
[linux@bashcommandnotfound.cn ~]$ gcov -l hello.c
File 'hello.c'
Lines executed:100.00% of 9
Creating 'hello.c.gcov'
-: 0:Source:hello.c
-: 0:Graph:hello.gcno
-: 0:Data:hello.gcda
-: 0:Runs:1
-: 0:Programs:1
-: 1:#include <stdio.h>
-: 2:
-: 3:int foo(int x) {
1: 4: if (x > 0) {
1: 5: return x + 1;
-: 6: } else {
1: 7: return x - 1;
-: 8: }
-: 9:}
-: 10:
1: 11:int main() {
1: 12: printf("Hello, world!\n");
1: 13: printf("foo(10) = %d\n", foo(10));
1: 14: printf("foo(-10) = %d\n", foo(-10));
1: 15: return 0;
-: 16:}
这里可以看到,每行代码前面有一个数字,表示该行代码被执行的次数。如果该行代码没有被执行,或者不是有效的代码行,例如空行或注释行,那么数字就是-。这样可以很清楚地看到程序的执行流程和覆盖情况。
实例6:不生成注释的源代码文件
使用gcov命令带上-n选项,可以不生成注释的源代码文件,只显示覆盖率信息。这样可以节省磁盘空间,或者避免覆盖原有的源代码文件。例如:
[linux@bashcommandnotfound.cn ~]$ gcov -n hello.c
File 'hello.c'
Lines executed:100.00% of 9
这里可以看到,gcov命令没有生成hello.c.gcov文件,只显示了总体覆盖率信息。
实例7:指定目标文件和源文件的目录
使用gcov命令带上-o和-s选项,可以指定目标文件和源文件的目录,如果它们不在当前目录或默认的目录中。例如,假设目标文件在~/obj目录中,源文件在~/src目录中,可以使用以下命令来分析覆盖率:
[linux@bashcommandnotfound.cn ~]$ gcov -o ~/obj -s ~/src hello.c
File 'hello.c'
Lines executed:100.00% of 9
Creating '~/src/hello.c.gcov'
这里可以看到,gcov命令在~/src目录中生成了注释的源代码文件。
实例8:在输出的文件名中保留源文件的路径信息
使用gcov命令带上-p选项,可以在输出的文件名中保留源文件的路径信息,而不是只显示文件名。这样可以避免不同目录中的同名文件产生冲突。例如,假设源文件在~/src/sub目录中,可以使用以下命令来分析覆盖率:
[linux@bashcommandnotfound.cn ~]$ gcov -p hello.c
File 'hello.c'
Lines executed:100.00% of 9
Creating '#home#user#src#sub#hello.c.gcov'
这里可以看到,gcov命令在当前目录中生成了一个名为#home#user#src#sub#hello.c.gcov的文件,其中#表示目录分隔符。
实例9:删除辅助文件
使用gcov命令带上-r选项,可以删除辅助文件,即.gcda和.gcno文件,这些文件是编译时和运行时生成的,用来存储覆盖率数据。如果不需要再分析覆盖率,可以使用这个选项来清理磁盘空间。例如:
[linux@bashcommandnotfound.cn ~]$ gcov -r hello.c
File 'hello.c'
Lines executed:100.00% of 9
Creating 'hello.c.gcov'
Removing 'hello.gcda'
Removing 'hello.gcno'
这里可以看到,gcov命令在生成注释的源代码文件后,删除了辅助文件。
实例10:显示调用图覆盖率信息
使用gcov命令带上-c选项,可以显示调用图覆盖率信息,即每个函数被调用的次数和调用者。这样可以更好地理解程序的结构和逻辑。例如:
[linux@bashcommandnotfound.cn ~]$ gcov -c hello.c
File 'hello.c'
Lines executed:100.00% of 9
Creating 'hello.c.gcov'
Function 'foo'
Lines executed:100.00% of 5
Called 2 times
Calls:
1: foo (called by main)
1: foo (called by main)
Function 'main'
Lines executed:100.00% of 4
Called 1 times
Calls:
1: printf (called by main)
1: printf (called by main)
1: foo (called by main)
1: printf (called by main)
1: foo (called by main)
这里可以看到,每个函数后面有一个Calls:的列表,显示了该函数被哪些函数调用,以及调用的次数。
Linux gcov命令的注意事项
使用gcov命令时,需要注意以下几点:
- gcov命令只能分析C、C++或Objective-C语言编写的程序,不能分析其他语言的程序。
- gcov命令需要在编译源文件时加上-g和-fprofile-arcs -ftest-coverage选项,否则无法生成覆盖率数据。
- gcov命令需要在运行程序后才能分析覆盖率,否则无法收集覆盖率数据。
- gcov命令的输出文件名和格式可能随着GCC版本的变化而变化,因此,建议使用相同版本的GCC和gcov命令,或者使用-gcov-tool命令来兼容不同版本的覆盖率数据。
- 如果在执行gcov命令时出现bash: gcov: command not found的错误,说明没有安装GCC或者没有将GCC的路径添加到环境变量中,可以使用以下命令来安装GCC或者查看GCC的路径:
[linux@bashcommandnotfound.cn ~]$ sudo yum install gcc # CentOS 7
[linux@bashcommandnotfound.cn ~]$ sudo dnf install gcc # CentOS 8
[linux@bashcommandnotfound.cn ~]$ which gcc
Linux gcov命令的相关命令
以下是一些和gcov命令相关的命令,可以用来辅助分析覆盖率或者生成更友好的报告:
评论区