gcov简介
gcov是什么
- gcov是一个测试代码覆盖率的工具。与GCC一起使用来分析程序,以帮助创建更高效、更快的运行代码,并发现程序的未测试部分
- 是一个命令行方式的控制台程序。需要结合lcov,gcovr等前端图形工具才能实现统计数据图形化
- 伴随GCC发布,不需要单独下载gcov工具。配合GCC共同实现对c/c++文件的语句覆盖和分支覆盖测试
- 与程序概要分析工具(profiling tool,例如gprof)一起工作,可以估计程序中哪段代码最耗时
gcov能做什么
使用象gcov或gprof这样的分析器,您可以找到一些基本的性能统计数据:
- 每一行代码执行的频率是多少
- 实际执行了哪些行代码,配合测试用例达到满意的覆盖率和预期工作
- 每段代码使用了多少计算时间,从而找到热点优化代码
- gcov创建一个sourcefile.gcov的日志文件,此文件标识源文件sourcefile.c每一行执行的次数,您可以与gprof一起使用这些日志文件来帮助优化程序的性能。gprof提供了您可以使用的时间信息以及从gcov获得的信息。
注意事项
- 通过将一些代码行合并到一个函数中,可能不会提供足够的信息来查找代码使用大量计算机时间的“热点”。同样地,由于gcov按行(在最低的分辨率下)积累统计数据,它最适合于只在每行上放置一个语句的编程风格。如果您使用扩展到循环或其他控制结构的复杂宏,那么统计信息就没有那么有用了——它们只报告出现宏调用的行。如果您的复杂宏的行为类似于函数,那么您可以用inline fu替换它们。
- gcov只在使用GCC编译的代码上工作。它与任何其他概要或测试覆盖机制不兼容。
gcov过程概况
![6f05bf91597bd4104bf587cd249b290f.png](https://i-blog.csdnimg.cn/blog_migrate/1949db66eacb7a9baf18a17b4322f6b9.jpeg)
gcov过程
主要工作流
- 编译前,在编译器中加入编译器参数-fprofile-arcs -ftest-coverage;
- 源码经过编译预处理,然后编译成汇编文件,在生成汇编文件的同时完成插桩。插桩是在生成汇编文件的阶段完成的,因此插桩是汇编时候的插桩,每个桩点插入3~4条汇编语句,直接插入生成的*.s文件中,最后汇编文件汇编生成目标文件,生成可执行文件;并且生成关联BB和ARC的.gcno文件;
- 执行可执行文件,在运行过程中之前插入桩点负责收集程序的执行信息。所谓桩点,其实就是一个变量,内存中的一个格子,对应的代码执行一次,则其值增加一次;
- 生成.gcda文件,其中有BB和ARC的执行统计次数等,由此经过加工可得到覆盖率。
使用gcov的3个阶段
编译阶段
要开启gcov功能,需要在源码编译参数中加入-fprofile-arcs -ftest-coverage
- -ftest-coverage:在编译的时候产生.gcno文件,它包含了重建基本块图和相应的块的源码的行号的信息。
- -fprofile-arcs:在运行编译过的程序的时候,会产生.gcda文件,它包含了弧跳变的次数等信息。
如下以helloworld_gcov.c为例子,源码如下:
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[])
{
if (argc >=2) {
printf("=====argc>=2n");
return;
}
printf("helloworld beginn");
if (argc <2){
printf("=====argc<2n");
return;
}
return;
}
helloworld_gcov.c的Makefile的书写如下,在编译选项CFLAGS中加入-fprofile-arcs -ftest-coverage选项:
#加入gcov编译选项,通过宏PRJRELEASE=gcov控制
ifeq ("$(PRJRELEASE)","gcov")
CFLAGS+= -fprofile-arcs -ftest-coverage
endif
CC=gcc
.PHONE: all
all: helloworld
helloworld: *.c
# 编译出汇编和gcno文件
@echo ${CFLAGS}
@${CC} ${CFLAGS} -S -o helloworld_gcov.s helloworld_gcov.c
@${CC} ${CFLAGS} -o helloworld_gcov helloworld_gcov.c
.PHONE: clean
clean:
@-rm hell