当两个可执行文件针对同一个源文件运行时,.gcda 文件覆盖率信息不会更新 [英] .gcda file coverage info not getting updated when two executables run for same source file

查看:20
本文介绍了当两个可执行文件针对同一个源文件运行时,.gcda 文件覆盖率信息不会更新的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

共有三个文件 u1.c 、 u2.c 和 common.c

ut1.c 的内容

#include<stdio.h>
void fun1();
int main(){
    fun1();
}

ut2.c 的内容

#include<stdio.h>
void fun2();
int main(){
    fun2();
}

common.c 的内容

content of common.c

void fun1(){
        printf("fun1\n");
}

void fun2(){
        printf("fun2\n");
}


编译步骤:-


Compilation steps:-

gcc -Wall -fprofile-arcs -ftest-coverage ut1.c common.c -o ut1
gcc -Wall -fprofile-arcs -ftest-coverage ut2.c common.c -o ut2

执行步骤:-

./ut1
./ut2

现在运行 gcov common.c 时,只有 fun2 覆盖.

Now when running gcov common.c only fun2 coverage is coming.

    -:    0:Source:common.c
    -:    0:Graph:common.gcno
    -:    0:Data:common.gcda
    -:    0:Runs:1
    -:    0:Programs:1
    -:    1:void fun1(){
    -:    2:        printf("fun1\n");
    -:    3:}
    -:    4:
    1:    5:void fun2(){
    1:    6:        printf("fun2\n");
    1:    7:}

推荐答案

这是因为您将 common.c 编译两次.

This is because you are compiling common.c two separate times.

在运行您的 ut1 和 ut2 程序时,我们可以看到以下警告(使用 GCC 10 测试):

When running your ut1 and ut2 programs, we can see the following warning (tested with GCC 10):

$ ./ut1
fun1
$ ./ut2
fun2
libgcov profiling error:/tmp/gcov-test/common.gcda:overwriting an existing profile data with a different timestamp

每次在启用覆盖率的情况下进行编译时,GCC 都会为覆盖率数据分配一个校验和.该校验和主要由 gcov 工具使用,以确保 gcno 文件和 gcda 文件匹配.在编译 ut1 和 ut2 时,将使用不同的校验和.因此,ut2 不会附加覆盖数据,而是看到无效的校验和并将覆盖数据.

Each time when you compile with coverage enabled, GCC will assign a checksum to the coverage data. This checksum is primarily used by the gcov tool to ensure that the gcno file and gcda files match. When compiling ut1 and ut2, different checksums will be used. So instead of appending coverage data, ut2 sees the invalid checksum and will overwrite the data.

解决办法是把common.c当作一个单独的编译单元,与ut1和ut2链接起来.例如:

The solution is to treat common.c as a separate compilation unit and link it with ut1 and ut2. For example:

# compile common.c
gcc -Wall --coverage -c common.c -o common.o

# compile ut1 and ut2, and link with common.o
gcc -Wall --coverage ut1.c common.o -o ut1
gcc -Wall --coverage ut2.c common.o -o ut2

然后,gcov 输出应该如预期的那样:

Then, the gcov output should be as expected:

        -:    0:Source:common.c
        -:    0:Graph:common.gcno
        -:    0:Data:common.gcda
        -:    0:Runs:2
        -:    1:#include<stdio.h>
        1:    2:void fun1(){
        1:    3:        printf("fun1\n");
        1:    4:}
        -:    5:
        1:    6:void fun2(){
        1:    7:        printf("fun2\n");
        1:    8:}

如果您无法更改项目的编译方式,您可以使用 lcov 或 gcovr 等工具收集覆盖数据,然后将其合并.例如,gcovr 的工作流程如下:

If you cannot change how your project is compiled, you could collect the coverage data with a tool such as lcov or gcovr, and then merge it. For example, the workflow with gcovr would be as follows:

  1. 编译ut1,执行它,并将覆盖数据保存为gcovr JSON报告:

  1. Compile ut1, execute it, and save the coverage data as a gcovr JSON report:

gcc -Wall --coverage ut1.c common.c -o ut1
./ut1
gcovr --json ut1.json
rm *.gcda *.gcno

  • 编译ut2,执行它,并将覆盖数据保存为gcovr JSON报告:

  • Compile ut2, execute it, and save the coverage data as a gcovr JSON report:

    gcc -Wall --coverage ut2.c common.c -o ut2
    ./ut2
    gcovr --json ut2.json
    

  • 创建合并报告:

  • Create a combined report:

    gcovr -a ut1.json -a ut2.json --html-details coverage.html
    

  • 虽然 gcovr 无法输出 gcov 样式的文本报告,但它可以将覆盖范围显示为 HTML:

    While gcovr cannot output gcov-style textual reports, it can show the coverage as HTML:

    此答案的完整代码位于 https://gist.github.com/latk/102b125dff160484f93d8997204fc201

    这篇关于当两个可执行文件针对同一个源文件运行时,.gcda 文件覆盖率信息不会更新的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆