gcov 和 switch 语句
Posted
技术标签:
【中文标题】gcov 和 switch 语句【英文标题】:gcov and switch statements 【发布时间】:2011-02-18 07:28:55 【问题描述】:我正在使用 switch 语句在一些 C 代码上运行 gcov。我编写了测试用例来涵盖通过该 switch 语句的所有可能路径,但它仍然报告 switch 语句中的一个分支未采用,并且在“至少采用一次”统计信息中低于 100%。
这里有一些示例代码来演示:
#include "stdio.h"
void foo(int i)
switch(i)
case 1:printf("a\n");break;
case 2:printf("b\n");break;
case 3:printf("c\n");break;
default: printf("other\n");
int main()
int i;
for(i=0;i<4;++i)
foo(i);
return 0;
我使用“gcc temp.c -fprofile-arcs -ftest-coverage
”构建,运行“a
”,然后运行“gcov -b -c temp.c
”。输出指示交换机上有八个分支,其中一个(分支 6)未使用。
所有这些分支是什么?如何获得 100% 的覆盖率?
【问题讨论】:
.gcda 文件的内容有帮助吗? 【参考方案1】:哦哦! bde 的程序集转储显示该版本的 GCC 正在将此 switch 语句编译为二叉树的某种近似,从集合的中间开始。所以它检查i
是否等于2,然后检查它是大于还是小于2,然后对于每一边它分别检查它是等于1还是3,如果不是,则默认。
这意味着它有两种不同的代码路径可以得到默认结果——一种用于大于 2 的非 3 数字,另一种用于小于 2 但不是 1 的数字。
如果您将循环中的 i<4
更改为 i<=4
,看起来您将获得 100% 的覆盖率,以便测试每一侧的路径。
(而且,是的,这很可能已经从 GCC 3.x 更改为 GCC 4.x。我不会说它是“固定的”,因为除了生成 gcov 结果之外,它并不是“错误的”令人困惑。只是在具有分支预测功能的现代处理器上,它可能很慢而且过于复杂。)
【讨论】:
【参考方案2】:我使用 gcc/gcov 3.4.6 得到了相同的结果。
对于 switch 语句,它通常应该为每个 case 语句生成两个分支。一个是案例是否为真并且应该被执行,另一个是一个“fallthrough”分支,继续到下一个案例。
在您的情况下,gcc 似乎正在为最后一种情况创建一个“fallthrough”分支,这没有任何意义,因为没有什么可陷入的。
这是 gcc 生成的汇编代码的摘录(为了便于阅读,我更改了一些标签):
cmpl $2, -4(%ebp)
je CASE2
cmpl $2, -4(%ebp)
jg L7
cmpl $1, -4(%ebp)
je CASE1
addl $1, LPBX1+16
adcl $0, LPBX1+20
jmp DEFAULT
L7:
cmpl $3, -4(%ebp)
je CASE3
addl $1, LPBX1+32
adcl $0, LPBX1+36
jmp DEFAULT
我承认我对 x86 汇编不太了解,也不了解 L7 标签的使用,但它可能与额外的分支有关。也许对 gcc 有更多了解的人可以解释这里发生了什么。
听起来这可能是旧版本的 gcc/gcov 的问题,升级到新的 gcc/gcov 可能会解决问题,特别是考虑到结果看起来正确的另一篇文章。
【讨论】:
我怀疑 gcov 是一个失败的分支;它看起来更有可能是 gcc 做的。如果开启优化会怎样?default
的失败并没有错:毕竟下面可能有一个case
以避免执行特定于default
的代码。问题在于 switch 的最后一个语句有一个失败,因为没有什么可以陷入的。
@***s 开启优化并没有改变问题,而且看起来如果我使用 -O3 或更高版本会增加更多分支。
@Matthieu 我同意,这更有意义。我已经编辑了我的回复以反映这一点。
@bde:啊,好吧。这么多的想法!【参考方案3】:
你确定你正在运行 a.out 吗?这是我的结果(gcc 4.4.1):
File 't.c'
Lines executed:100.00% of 11
Branches executed:100.00% of 6
Taken at least once:100.00% of 6
Calls executed:100.00% of 5
t.c:creating 't.c.gcov'
【讨论】:
他说ran "a"
,对我来说这表明他运行a.exe
并且正在使用Windows。
我想——默认情况下,我将 gcc 与 unix 相关联。结果看起来与意外运行不同版本的可执行文件一致。
是的,我在 Windows 上使用 MinGW,它是 gcc 3.4.5。这可能是最新版本的 gcc 中修复的问题吗?【参考方案4】:
我在 windows 上使用 mingw(这不是最新的 gcc),看起来这可能会在较新版本的 gcc 中解决。
【讨论】:
以上是关于gcov 和 switch 语句的主要内容,如果未能解决你的问题,请参考以下文章