3、Gcov实战:运行程序生成.gcda文件、使用Gcov生成报告、解读Gcov报告、常见问题排查
好,咱们进入实战环节。前面两章我们把Gcov的原理和编译选项讲清楚了,这一章我带你亲手跑一遍完整的流程。从编译、运行、生成报告,到排查那些让人头疼的坑,咱们一步到位。
3.1 编译与运行:让.gcda文件诞生
先说说我的习惯。我一般会在Makefile里单独维护一个coverage编译目标,跟生产环境的编译选项完全分开。这样不会污染正式构建,也方便反复跑覆盖率。
编译时,必须加上两个关键flag:
gcc -fprofile-arcs -ftest-coverage -o test_program test.c
解释一下:
-fprofile-arcs:告诉编译器插入计数代码,记录每条边(分支)的执行次数-ftest-coverage:生成.gcno文件,里面存的是代码的静态结构信息
编译完你会看到两个文件:test.gcno 和可执行文件 test_program。.gcno文件是静态的,编译一次就不变了。真正的动态数据,得等程序跑起来才会产生。
运行程序:
./test_program
跑完之后,当前目录下会多出一个 test.gcda 文件。这就是覆盖率分析的“原油”——里面记录了每一行代码、每一个分支的执行次数。
3.2 使用Gcov生成报告
有了.gcda文件,接下来就是见证奇迹的时刻。运行:
gcov test.c
Gcov会读取 test.gcno 和 test.gcda,然后生成一个 test.c.gcov 文件。这个文件就是人类可读的覆盖率报告。
如果你想生成更友好的格式,可以用 -b 选项看分支覆盖率,用 -f 看每个函数的覆盖率:
gcov -b -f test.c
我个人习惯用 gcov -b -f -o . test.c,其中 -o . 指定.gcda文件的搜索路径。如果你的.gcda文件在别的目录,这个参数就很有用了。
3.3 解读Gcov报告
打开生成的 test.c.gcov 文件,你会看到类似这样的内容:
-: 0:Source:test.c
-: 0:Graph:test.gcno
-: 0:Data:test.gcda
-: 1:#include <stdio.h>
1: 2:int main() {
1: 3: int x = 10;
1: 4: if (x > 5) {
1: 5: printf("x is greater than 5\n");
-: 6: } else {
#####: 7: printf("x is not greater than 5\n");
-: 8: }
1: 9: return 0;
-: 10:}
每一行前面的数字代表执行次数:
- 数字(如
1):该行被执行了多少次 #####:该行从未被执行过(未覆盖)-:非可执行行(注释、空行、大括号等)
你看第7行,前面是 #####,说明else分支从来没走到过。这就是典型的“分支未覆盖”。
- 行覆盖率:被执行的代码行数 / 总可执行行数
- 分支覆盖率:被覆盖的分支数 / 总分分支数
- 函数覆盖率:被调用的函数数 / 总函数数
我一般先看函数覆盖率,如果某个函数是0%,那说明测试用例根本没调用它。再看分支覆盖率,这里最容易漏掉边界条件。
3.4 常见问题排查
做覆盖率分析这么多年,我踩过的坑能写一本书。这里挑几个高频问题说说。
3.4.1 .gcda文件没生成
原因: 程序异常退出、被kill、或者没有写权限。
排查: 先确认程序正常跑完了。可以用 echo $? 检查退出码。如果程序是被 SIGKILL 杀掉的,Gcov根本来不及写数据。
3.4.2 报告显示全是 #####
原因: .gcno和.gcda版本不匹配,或者编译后重新链接了。
排查: 重新编译一遍,重新跑测试。记住:编译和运行必须在同一份代码上,不能改了代码不重新编译。
3.4.3 报告里出现 ??? 或乱码
原因: 源文件路径变了,或者.gcno文件损坏。
排查: 用 gcov -o <path> test.c 指定正确的路径。如果还不行,删掉所有.gcno和.gcda,重新来一遍。
3.4.4 分支覆盖率总是偏低
这个其实不是工具的问题,是测试用例设计的问题。你想想看,if-else语句有两条分支,你只测了true分支,false分支自然就是0%。
我的建议是:写测试用例时,对着代码画个控制流图,确保每个分支都走到。特别是边界条件——比如 if (x > 0),你至少要测 x=1 和 x=0 两种情况。
3.5 本章知识体系
下面这张图,是我自己总结的Gcov实战流程,你照着走基本不会出错:
嗯,这张图把整个流程串起来了。你从编译开始,拿到.gcno和可执行文件;然后运行程序,生成.gcda;接着用gcov命令生成报告;最后解读报告,发现问题就补充测试用例,再重新跑一遍。循环往复,直到覆盖率达标。
好了,这一章的内容就到这里。你照着上面的步骤走一遍,基本就能掌握Gcov的实战用法了。遇到问题别慌,先检查.gcda有没有生成,再看报告里的 ##### 集中在哪些行,对症下药就行。