代码覆盖率(Lcov)错误地显示100%覆盖率

6

我有以下设置(使用g++ 10和lcov 1.14):

g++ SampleScript.cpp -g -O0 -fprofile-arcs -ftest-coverage -o MyScript
./MyScript

lcov -d . -c -o coverage.info --rc lcov_branch_coverage=1
genhtml coverage.info -o cov_out --legend --branch-coverage

/* SampleScript.cpp */

class Container
{
public:
    Container()
        : m_value(0) { }

    Container(int value)
        : m_value(value) { }

    int& value()
    {
        return m_value;
    }

    const int& value() const
    {
        return m_value;
    }

private:
    int m_value;
};

int main()
{
    const Container c;
    return c.value();
}


但生成的输出结果显示覆盖率为100%,尽管我的代码跳过了两个函数(1个构造函数和1个value()函数)。我是否缺少任何设置?

lcov截图

1个回答

3
因为这些函数被标记为内联函数。当成员函数在类/结构体定义内部被定义时,它是一个隐式的内联函数。编译器只有在调用内联函数时才会生成代码。而lcov使用GCC内置的gcov覆盖机制,该机制基于将计数器插入生成的机器代码中。因此:
  • 编译器不会为这些函数生成代码
  • 因此gcov不知道这些函数的存在
  • 因此lcov也不知道这些函数的存在
这是所有gcov/lcov/gcovr风格覆盖工具的系统限制。
如果您想确保这些工具能够识别未覆盖的函数,请确保它们不是内联函数(并具有外部链接),或者确保您的测试包含对该函数的调用(即使从未执行该调用)。或者使用解析源代码本身的不同覆盖工具。
C++中的内联概念并不是指内联优化,而更多地与链接和单一定义规则(ODR)相关。函数/对象的定义必须在使用它们的所有编译单元中可见,并且链接器可以合并否则冲突的定义(ODR的例外情况)。相反,如果没有使用内联函数,编译器通常不会生成代码。当使用inline关键字标记函数或在类/结构体的主体中定义时,函数可以是内联的:
struct Example {
  void inline_function() { ... }
  void also_inline();
  void not_inline();
};

inline void Example::also_inline() { ... }

void Example::not_inline() { ... }

1
谢谢。我该如何(a)确保函数不被内联,或者(b)确保我的测试包含“对该函数的调用,即使调用从未执行”? - Phil-ZXX
@Phil-ZXX 我编辑了答案,并简要讨论了C++的“inline”概念。(a) 你可以在类中声明函数签名,然后在外部定义 int& Container::value() { ... }。(b) 抱歉,我可能把它弄得比必要的还要复杂。如果你在某个地方调用该函数,则会生成该函数的代码。当然,你也可以为其编写一个测试用例,因此这个建议在实践中并不是那么有用... - amon

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接