【问题标题】:Unexpected branch count in coverage data覆盖数据中的意外分支计数
【发布时间】:2016-11-23 13:14:39
【问题描述】:

我生成覆盖数据并使用在线服务进行可视化和 CI。但是我有奇怪的“部分”(没有完全覆盖的 if 分支)。查看 gcov 数据,似乎检测到了过多的分支。

一个例子:

function _ZNK5World8AdjustBQE5PointItEh15BuildingQuality called 415 returned 100% blocks executed 76%
      415:  377:BuildingQuality World::AdjustBQ(const MapPoint pt, unsigned char player, BuildingQuality nodeBQ) const
        -:  378:{
      415:  379:    if(nodeBQ == BQ_NOTHING || GetNode(pt).owner != player + 1 || !IsPlayerTerritory(pt))
branch  0 taken 95% (fallthrough)
branch  1 taken 5%
call    2 returned 100%
call    3 returned 100%
branch  4 taken 100% (fallthrough)
branch  5 taken 0% (throw)
branch  6 taken 85% (fallthrough)
branch  7 taken 15%
call    8 returned 100%
call    9 returned 100%
branch 10 taken 100% (fallthrough)
branch 11 taken 0% (throw)
branch 12 taken 17% (fallthrough)
branch 13 taken 83%
branch 14 taken 80% (fallthrough)
branch 15 taken 20%
branch 16 taken 95% (fallthrough)
branch 17 taken 5%
branch 18 taken 33% (fallthrough)
branch 19 taken 67%
branch 20 never executed
branch 21 never executed
branch 22 never executed
branch 23 never executed
call   24 never executed

虽然我已经在使用-g -O0 --coverage -fno-default-inline -fno-inline 进行编译,但这些函数似乎仍然被内联和计数。我该怎么办,所以我只能得到“有意义的”数据,并且内联函数在其定义中被正确归因?

我正在使用 g++-4.8 和 gcov-4.8

编辑:如果我将 if 拆分为它的调用,我会得到:

      415:  379:    unsigned char owner = GetNode(pt).owner;
call    0 returned 100%
call    1 returned 100%
branch  2 taken 100% (fallthrough)
branch  3 taken 0% (throw)
call    4 never executed
      415:  380:    bool isPlayerTer = IsPlayerTerritory(pt);
call    0 returned 100%
call    1 returned 100%
branch  2 taken 100% (fallthrough)
branch  3 taken 0% (throw)
call    4 never executed
      415:  381:    if(nodeBQ == BQ_NOTHING || owner != player + 1 || !isPlayerTer)
branch  0 taken 95% (fallthrough)
branch  1 taken 5%
branch  2 taken 85% (fallthrough)
branch  3 taken 15%
branch  4 taken 17% (fallthrough)
branch  5 taken 83%

所以问题真的出在电话上。我该怎么做才能使这些调用(及其分支 (???))不被添加到覆盖数据中?

刚刚在 asm 代码中发现了一个人工分支,它只检查一个寄存器并执行 nop(除了 gcov 计数器增量)WTF?

   0x0000000000d967de <World::AdjustBQ(Point<unsigned short>, unsigned char, BuildingQuality) const+340>:   test   %bl,%bl
   0x0000000000d967e0 <World::AdjustBQ(Point<unsigned short>, unsigned char, BuildingQuality) const+342>:   je     0xd967f5 <World::AdjustBQ(Point<unsigned short>, unsigned char, BuildingQuality) const+363>
   0x0000000000d967e2 <World::AdjustBQ(Point<unsigned short>, unsigned char, BuildingQuality) const+344>:   nop
   0x0000000000d967e3 <World::AdjustBQ(Point<unsigned short>, unsigned char, BuildingQuality) const+345>:   mov    0x1206c9e(%rip),%rax        # 0x1f9d488 <__gcov0._ZNK5World8AdjustBQE5PointItEh15BuildingQuality+72>
   0x0000000000d967ea <World::AdjustBQ(Point<unsigned short>, unsigned char, BuildingQuality) const+352>:   add    $0x1,%rax
   0x0000000000d967ee <World::AdjustBQ(Point<unsigned short>, unsigned char, BuildingQuality) const+356>:   mov    %rax,0x1206c93(%rip)        # 0x1f9d488 <__gcov0._ZNK5World8AdjustBQE5PointItEh15BuildingQuality+72>
   0x0000000000d967f5 <World::AdjustBQ(Point<unsigned short>, unsigned char, BuildingQuality) const+363>:   test   %dl,%dl

我切换到 clang++ 和 llvm-cov gcov 并得到了这个案例的正确结果(只有 6 个分支)。然而,我在其他地方也得到了一些误报。最令人不安的一个似乎是“函数 __cxx_global_array_dtor 调用”,位于函数中间的类似行(仅更改整数参数)没有这个的行。所以我目前的解决方案是使用没有分支数据的 gcov-4.8,因为它完全不可靠。

【问题讨论】:

    标签: c++ code-coverage gcov


    【解决方案1】:

    在可能发生异常的点上可能存在额外的分支,例如在函数调用点。

    例如,我们在(不是 noexcept)空的虚拟析构函数中观察到一个带有 gcov 的分支,我们的测试无法覆盖它。

    【讨论】:

    • 这个:stackoverflow.com/questions/7199360/… ?但是,这是呼叫站点。呼叫站点不应该有任何分支机构,应该有吗?
    • 有趣的评论。我们观察到的分支似乎来自动态/非动态区分,而不是来自异常分支。然后我们可以通过测试来解决这个问题。我会在星期一试试。
    猜你喜欢
    • 2019-11-26
    • 2011-12-15
    • 2022-01-06
    • 2023-03-13
    • 2020-08-19
    • 2021-03-28
    • 2018-11-15
    • 2012-09-03
    • 2015-04-10
    相关资源
    最近更新 更多