在并行运行时使用 gcov 的代码覆盖率

Code coverage using gcov on parallel run

本文关键字:gcov 代码覆盖率 并行 运行时      更新时间:2023-10-16

我为项目中的几个文件设置了 c/C++ 代码覆盖率和 gcov。可执行文件正在并行运行。这会导致一些共享代码段并行运行。

我得到损坏的.da文件

或零大小的.da文件。这是并行运行的问题吗?

因为两个或多个可执行实例正在尝试写入同一个 .da 文件以写入执行中每个语句的覆盖率计数?

如果是这样,是否有任何解决方法?

使用的 Gcov 版本是 1.5

我也有类似的需求,我通过设置GCOV_PREFIX环境变量来解决它。

根据文档:

GCOV_PREFIX包含要添加到对象文件中的绝对路径的前缀。前缀可以是绝对的,也可以是相对的。默认值为无前缀。

GCOV_PREFIX设置为自定义目录,对于每个可执行文件+执行都是唯一的,将强制运行时在指定目录中生成".gcda",而不是使用编译目录(".gcno"所在的位置)。

完成所有执行后,您将能够使用它们来生成合并运行的报告。

好吧,

您似乎已经找到了问题的根本原因并正在寻找解决方法。
我已经成功地配置了几个项目来使用 gcov 进行代码覆盖。
我想为您澄清几件事:

  • 我们在编译期间使用--coverage选项检测的每个源文件.gcno文件。
  • 在执行时,我们为每个 gcno 文件获取.gcda个文件。

.gcno文件只是相关源代码文件的流程图结构。
.gcda文件是在执行时生成的实际覆盖数据。

因此,在您的情况下,当两个或多个执行尝试同时写入相同的.gcda文件时,.gcda(在早期版本中.da)会发生冲突。

最简单的解决方法是串行运行测试。(至少我是这样做的)
您无需担心丢失覆盖率数据,因为每次执行都会附加.gcda数据而不会被覆盖。请记住,您不必进行重新编译,因为它会更改.gcno文件,并且以前的.gcda文件将变得无用。

较新 (9+) 版本的 GCC 中的另一种解决方案支持 %p -fprofile-dir 中的模式:

-fprofile-dir=coverage.%p

这允许避免每次都显式重新生成GCOV_PREFIX环境变量。它还支持分析更复杂的用例,例如递归运行相同的程序/库(clanggcc是这样的)。

收集覆盖范围后,您可以在gcov-tool-many的帮助下将其组合在一起(这是一个包装器,一次只能组合两个配置文件gcov-tool):

# Combine coverages
$ scripts/gcov-tool-many merge coverage.*
# Get rid of mangled names like #home#user#myproject#bin#main.gcda
for f in `find -name '#*.gc[dn][ao]'`; do
  mv $f $(basename $f | tr # /)
done
# Generate the report
gcov *.gcno