首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么GCOV声称这一行不包括在内?

为什么GCOV声称这一行不包括在内?
EN

Stack Overflow用户
提问于 2021-12-29 01:58:09
回答 1查看 867关注 0票数 2

我最近升级到了gcc/g++/gcov的新版本,现在gcov的行为很奇怪。新版本声称,一些代码行没有涵盖,而这些代码被认为是旧版本所涵盖的。我设法将我的代码简化为这个最小的例子。

代码语言:javascript
复制
#include <memory>
using namespace std;
struct S {};

int main() {
    unique_ptr<S> s;
    s = make_unique<S>();
}

然后使用g++ -O0 -Wall -Wextra -Werror --std=c++17 --coverage编译这个文件,运行生成的a.out,然后运行gcov

生成的.gcov文件包含:

代码语言:javascript
复制
    -:    0:Runs:1
    -:    1:#include <memory>
    -:    2:using namespace std;
    -:    3:struct S {};
    -:    4:
    1:    5:int main() {
#####:    6:    unique_ptr<S> s;
    1:    7:    s = make_unique<S>();
    1:    8:}

这与较早版本的gcov不同,后者声称第6行被击中了2次。

为什么gcov认为第6行没有涵盖?我做错了什么吗?

我能够用gcc8、gcc9和gcc10再现这种行为。gcc7的行为与预期相同。

编译器资源管理器比较gcc7 7/8:https://godbolt.org/z/Te57s4WK8

EN

回答 1

Stack Overflow用户

发布于 2021-12-30 00:24:10

破坏者。通过更新到最近的GCC,或者使用更多的工具过滤掉覆盖范围。

这两个编译器生成的程序集几乎是相同的,但是这里的程序集并不是完整的。相关部分是gcov如何将程序集代码的部分与源代码关联。Gcov不为此使用调试信息。相反,无论何时输入基本块,gcov都会检测代码以增加计数器。块是没有内部控制流的程序集代码的一部分。Gcov使用其gcno文件将计数器ID与部分源代码相关联。

这两个编译器版本(GCC 7和8)都生成了三个与std::unique_ptr<S> s;声明相关的程序集片段:

初始化variable

  • destructor调用1的
  • (普通exit)
  • destructor调用2(用于因异常而展开)

现在发生的情况是,前两个片段不形成自己的块。它们是块的一部分,其中包括来自周围行的代码。特别是,在调试信息中,gcov计数器的代码被归因于其他行。只有异常处理程序行的块包含明确归因于所述行的计数器。因此,GCC的不同版本表现出不同程度的混乱是可以理解的。混淆似乎更大,因为gcov没有将未发现的代码标记为仅为例外。

最终,要搞清楚gcov是什么“思考”是不可能的。在我的经验中,异常对GCC的良好代码覆盖率是有害的,因为异常需要额外的代码路径。在某些情况下,可以使用-fno-exceptions进行编译。这将使您获得完美的代码覆盖率,但它会显着地改变语言。我不喜欢这样。

用GCC 11编译似乎解决了你的问题。它产生与GCC 8、9或10不同的程序集。覆盖报告将显示所覆盖的所有行,并正确地注意到一个块被打开(如果您使用gcov -a)。

如果您不能切换到最近的GCC,您可以考虑使用第三方工具将此类线路排除在保险范围之外。例如,gcovr和lcov允许您用排除标记对这些行进行注释。

代码语言:javascript
复制
std::unique_ptr<S> s;  // LCOV_EXCL_LINE

Gcovr还允许您定义自定义regex。例如,您可以使用:

代码语言:javascript
复制
gcovr --exclude-lines-by-pattern '(?x) ^ \s* unique_ptr<.*> \s* \w+; $'
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70514398

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档