了解lcov分支覆盖输出中的控制流图

sig*_*igy 6 c++ code-coverage gcov lcov control-flow-graph

我正在尝试通过检查我当前的代码覆盖百分比来改进我的单元测试.我正在使用gcov和lcov生成覆盖结果的HTML报告.但是,我在理解某些输出时遇到了问题.我知道a +表示已经采取了分支并且-没有采取分支.

131                 :          8 :         QString toString() const
132                 :            :         {
133 [ +  - ][ +  - ]:          8 :             return ((negative && !isZero()) ? "-" : "") + QString::number(sec) + "." + QString::number(nano).rightJustified(9, '0');
    [ +  - ][ +  + ]
    [ +  - ][ +  - ]
    [ +  - ][ +  - ]
            [ +  - ]
134                 :            :         }
Run Code Online (Sandbox Code Playgroud)

变量negative的类型为bool,因为是方法的返回值isZero.所以我希望这里有四个分支,但我不知道输出如何映射到这个期望.那么如何解释输出?悬停在+/-标志上时的工具提示告诉我分支3,6,9,11,12,14,17,20,23和26是在分支4,7,10,15,18,21,24和27人从未被带走过.

Bru*_*Sun 1

请参考[这里]的答案如下[1]:

简而言之,lcov 与分支的交互,特别是与内联调用的交互,可以找到代码中的一些隐藏分支,这些分支是您无法控制的。

例如,编译器可以有效地内联模板化函数(其中 std::cout << "foo" 就是其中之一)。这意味着编译器也可以看到该代码中存在的任何分支。这当然可以让编译器做更彻底的优化。这就是您在这里看到的分支。它不在您编写的代码中,而是在模板为您实例化的代码中。

特别是,basic_ostream 上的大多数格式化输出函数将确保在进行格式化或插入工作之前流处于良好状态。

当我进行分支分析时,我倾向于忽略此类函数的分支缺失。C++中有几个类似的地方由gcov/lcov检测分支,但只是实现细节。我尝试将注意力集中在我控制的分支上。

这里的原因是相同的,QString::number()是一个静态函数,它调用一个内联函数[QString::setNum][2],该函数内部有很多分支。

可以检查下面的例子来说明这一点:

foo.h

extern void foo(int);

class Bar {
    public:
        inline bool doCheckInt(int a) { return a > 0 && a < 2; }


        static bool checkParam(int a) {
            Bar bar;
            return bar.doCheckInt(a);

        }
};
Run Code Online (Sandbox Code Playgroud)

foo.cpp

#include "foo.h"
#include <iostream>

void foo(int num)
{
    if (Bar::checkParam(num)) {
        std::cout << "when num is equal to 1..." << std::endl;
    } else if (num == 2){
        std::cout << "when num is equal to 2..." << std::endl;
    } else {
        std::cout << "when num is equal to "<< num << std::endl;
    }
}
Run Code Online (Sandbox Code Playgroud)

主程序

#include <stdio.h>
#include "foo.h"
 

 int main(void)
 {
    printf("Start calling foo() ...\n");
    foo(1);
    foo(2);
    return 0;
 }
Run Code Online (Sandbox Code Playgroud)

编译并生成代码覆盖率报告(相关方法参考[此处][3])后,可以获得以下函数 foo() 的覆盖率报告:

[![foo_coverage][4]][4]

我们可以发现 foo 总共有 8 个分支(2 X 2 X 2),两个 foo(1)、foo(2) 命中了其中的 5 个分支。[1]: https: //stackoverflow.com/a/69164983/4277805 [2]:https://github.com/radekp/qt/blob/master/src/corelib/tools/qstring.h [3]:https://shenxianpeng.github.io/2021/07/gcov-example/ [4]: https://i.stack.imgur.com/n6huJ.png