gcov和switch语句

我用switch语句在一些C代码上运行gcov。 我已经编写了测试用例来覆盖通过switch语句的每条可能路径,但它仍然在switch语句中报告没有采用的分支,并且在“采取至少一次”状态下报告的分支不到100%。

这里有一些示例代码来演示:

#include "stdio.h"

void foo(int i)
{
    switch(i)
    {
        case 1:printf("an");break;
        case 2:printf("bn");break;
        case 3:printf("cn");break;
        default: printf("othern");
    }
}

int main()
{
    int i;
    for(i=0;i<4;++i)
        foo(i);
    return 0;
}

我用“ gcc temp.c -fprofile-arcs -ftest-coveragegcc temp.c -fprofile-arcs -ftest-coverage ,运行“ a ”,然后执行“ gcov -b -c temp.c ”。 输出指示交换机上有八个分支,一个(分支6)未被占用。

什么是所有这些分支机构,我如何获得100%的覆盖率?


啊哈! bde的程序集转储显示该版本的GCC正在将此开关语句编译为二叉树的一些近似值,从该集的中间开始。 所以它检查i是否等于2,然后检查它是大于还是小于2,然后对每一边检查它是否分别等于1或3,如果不相等,则它将进入默认值。

这意味着它有两种不同的代码路径可以获得默认结果 - 一个是高于2的数字不是3,另一个是低于2的数字不是1。

看起来,如果你改变,你会得到100%的覆盖率i<4在循环到i<=4 ,以便测试每边的路径。

(而且,是的,这很可能已经从GCC 3.x变为GCC 4.x.我不会说它是“固定的”,因为除了使gcov结果混淆外,它不是“错误的”。只是在具有分支预测的现代处理器上,它可能很慢并且过于复杂。)


我使用gcc / gcov 3.4.6获得了相同的结果。

对于switch语句,通常应该为每个case语句生成两个分支。 一个是如果案件是真实的并且应该被执行,另一个是“下落”分支继续下一个案件。

在你的情况下,看起来海湾合作委员会正在为最后一个案例制定一个“延期”分支,这是没有意义的,因为没有什么可以陷入。

下面是由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可能会解决问题,尤其是考虑到结果看起来正确的其他帖子。


你确定你正在运行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'
链接地址: http://www.djcxy.com/p/51003.html

上一篇: gcov and switch statements

下一篇: Impact of Xcode build options "Enable bitcode" Yes/No