【问题标题】:Code coverage missing a branch if a function takes reference parameter如果函数采用引用参数,则代码覆盖率缺少分支
【发布时间】:2019-01-29 09:36:24
【问题描述】:

我有一个带有引用参数的函数:

#include <iostream>

class A { static void TestA(const int &y) };

void A::TestA(const int &y) { std::cout << y; }

int main()
{
   A::TestA(2);
   return 0;
}

在我使用 google 单元测试的 (lcov) 代码覆盖率中,它说缺少一个带有 TestA() 函数的分支,并且符号列表添加了一个 stack_chk_fail 符号。如果我将函数参数更改为非引用,则覆盖率为 100%。

我正在使用 g++ 编译器。

我错过了什么吗?

谢谢

【问题讨论】:

  • 你用的是什么编译器?它的哪个版本?您在构建时使用什么标志?什么优化级别?你有没有检查过生成的代码,看看它到底做了什么?
  • 你的意思是当你通过你的测试覆盖工具运行这个短程序时,它会标记一些东西?如果没有,为什么我们看到的是这个程序而不是正确的minimal reproducible example
  • 什么是“我的代码覆盖率”?不清楚你在问什么,你已经在问题中说明你缺少什么
  • 好吧好吧……我的第一条评论是错误的。我可以在我的系统上重现它。
  • @StoryTeller 我已经更新了我的代码,并添加了我的测试细节。

标签: c++ reference code-coverage


【解决方案1】:

编译器将Test 内联到main(因为这是一个好的编译器所做的)。但是,它也必须Test 创建代码,因为它具有外部链接。实际上,该函数的代码存在两次:一次内联到 main 中,一次内联到 Test 的代码中,链接器可以与其他编译单元链接。

如果你的编译器对内联函数(你好 MSVC?)的代码属性(在调试符号中)不好,那么你的分析器会给出你看到的结果:执行程序不会导致 Test 的覆盖,因为执行的二进制文件(即main)没有任何行归属于Test

更改参数类型可能会影响内联,但更有可能会更改调试符号的生成方式。

要验证这一点,请使用调试器单步执行程序,并在Test 中设置断点。如果在运行main 时未命中该断点,则您的覆盖工具也不会看到该行的覆盖范围。或者,如果您确实需要,请手动查看调试符号以查看哪些行具有属性。在 Visual Studio 中,您还可以在调试时查看反汇编(它将显示相关的代码行)。

由于上述原因,如果您使用调试版本进行覆盖运行(例如不会发生内联),通常会获得更可靠的覆盖结果。

【讨论】:

  • 嗨!感谢你的回答。我已经用更好的示例和有关我的测试的更多详细信息更新了我的代码。你能再检查一下吗?顺便说一句,我能够达到断点。还有为什么当它是非引用指针时它工作正常?
猜你喜欢
  • 1970-01-01
  • 2012-01-11
  • 2016-08-11
  • 1970-01-01
  • 2016-09-08
  • 1970-01-01
  • 2012-02-02
  • 2017-05-18
  • 1970-01-01
相关资源
最近更新 更多