如何处理 Coveragescanner 错误信息和建议

警告 "coutuation is different" 的意思是什么?

在进行 C/C++ 程序的编译过程中,Coco 可能会发出如下形式的警告

Warning (Squish Coco): Compilation of 'myproject/header.h': Instrumentation of source file 'myproject/header.h' is different

随后的几行。这意味着什么?

说明

在 C 和 C++ 中,源文件的内容并不完全决定它编译成哪些代码。这是因为预处理符号可以在编译时设置,并通过 #ifdef 语句等通常方式决定哪些源代码实际上被转换。

这意味着源文件可能因为不同的预处理设置而被编译多次。这可能会导致不同的编译代码,如果 Coco 参与,则可能导致同一文件的不同的节流。如果 Coco 发现这种情况,它会发出 "Instrumentation is different" 的消息。

然而,该消息只是一个警告。Coco 将文件的不同版本视为不同的文件,并在 CoverageBrowser 或报告中用末尾的数字区分它们。如果有两个版本的头文件 header.h,则可以显示为 header.h#1header.h#2

示例

接下来是一个示例,通过这个示例可以更清楚地了解发生了什么以及如何理解错误消息。首先需要一个源文件,这个文件可以根据外部设置编译成不同的代码。以下文件 header.h 是这样的源。它定义了一个函数,letter(),它的编译取决于预处理符号 A 是否定义。

#ifndef HEADER_H
#define HEADER_H

static inline char letter()
{
#ifdef A
    return 'a';
#else
    return 'b';
#endif
}

#endif

然后是两个使用此库的文件。一个是 a.cpp

#include "a.h"
#include "header.h"
#include <iostream>

void a()
{
    std::cout << "Letter A: " << letter() << "\n";
}

另一个是 b.cpp。(这里省略了头文件 a.hb.h)。

#include "b.h"
#include "header.h"
#include <iostream>

void b()
{
    std::cout << "Letter B: " << letter() << "\n";
}

请注意,这两个文件在本质上完全相同,并且它们本身不包含受符号 A 影响的任何代码。然而,它们都包含了 header.h。这意味着 a.cppb.cpp 的预处理版本——CoverageScanner 看到并对其进行了仪器化处理——包含了一个预处理版本的 header.h,并且它们依赖于符号 A

最后,有一个程序,main.cpp,它使用它们两个。

#include "a.h"
#include "b.h"

int main()
{
    a();
    b();
    return 0;
}

所有这些文件都必须进行编译,但 a.cppb.cpp 必须使用不同的标志编译:对于 a.cpp,应该定义符号 A,但不应该为 b.cpp 定义。如果这个项目是用 makefile 编译的,它可能看起来像这样;

main: main.cpp a.o b.o
    g++ -o main main.cpp a.o b.o

a.o: a.cpp a.h header.h
    g++ -DA -c -o a.o a.cpp

b.o: b.cpp b.h header.h
    g++     -c -o b.o b.cpp

在这里可以看到,在 a.cpp 的编译中添加了额外的标志 -DA;它定义了符号 A。在其他构建系统中,设置将类似。

当这样的项目启用仪器化进行编译时,会发出上述警告。其全文是

Warning (Squish Coco): Compilation of 'myproject/header.h': Instrumentation of source file 'myproject/header.h' is different
Warning (Squish Coco):   Source line 7 of file 'myproject/header.h' is differently instrumented in the database 'main.csmes' and 'b.o.csmes'
Warning (Squish Coco): Original:
Warning (Squish Coco):     4: inline char letter()
Warning (Squish Coco):     5: {
Warning (Squish Coco):     6: #ifdef A
Warning (Squish Coco): >>> 7:     return 'a';
Warning (Squish Coco):     8: #else
Warning (Squish Coco):     9:     return 'b';
Warning (Squish Coco):     10: #endif
Warning (Squish Coco): [ALL] Inconsistent instrumentations in: myproject/header.h
Warning (Squish Coco):
Warning (Squish Coco): [1/2] Source files:                     myproject/a.cpp
Warning (Squish Coco): [1/2] Distinct define flags:            -DA
Warning (Squish Coco):
Warning (Squish Coco): [2/2] Source files:                     myproject/b.cpp
Warning (Squish Coco):
Warning (Squish Coco): [ALL] Common instrumentation options:   --cs-combine-switch-cases
Warning (Squish Coco):                                         --cs-count
Warning (Squish Coco):                                         --cs-function-coverage
Warning (Squish Coco):                                         --cs-line-coverage
Warning (Squish Coco):                                         --cs-mcc

在这里可以看到

  • 第一行显示错误发生在编译文件 header.h 期间。
  • 第二行显示,当从文件 b.o.csmes 中的信息合并到文件 main.csmes 中时发现的问题,并且它发生在第 7 行。

    实际上发生的事情是,最初,main.csmes 中没有包含任何有关 header.h 的信息。然后在链接步骤期间,合并了 a.o.csmes。它包含关于定义了符号 A 的版本的 header.h 的信息。然后,也合并了 b.o.csmes——包含了一个不同的版本的 header.h。这导致了不一致性。

  • 接下来的几行显示了不同的仪器化行:它是带有 return 'a'; 的行和只有定义了 A 时才部分包含的代码的第一行。

    此行的前后各有三行也被显示出来。上下文行的数量可以通过标志 –cs-verbose-source-lines 设置。

  • 这些差异可能是由于编译器选项引起的。以下从以 [ALL] 开头的第一行开始的几行,总结了对选项的易于阅读的格式。

    总结包括几个部分,每个部分都由方括号中的表达式作为前缀。前缀可以是 [ALL] 或类似 [1/2] 类似的内容。以 [ALL] 开头的行引用所有文件,而其他行引用一组组编译了相同命令行选项的文件。第一个数字是文件组的编号,第二个是所有文件组的编号。这意味着 [1/2] 指的是两个组中的第一个组。

    所有文件组部分具有相同的格式:首先有一行列出了组的 内容。在我们的例子中,第一个组(也是第二个)只包含一个文件

    Warning (Squish Coco): [1/2] Source files:                     myproject/a.cpp

    然后列出唯一的定义标志,即那些不在所有组中出现的标志。在第 个组中,这是预料之中的,因为它只为文件 a.cpp 定义了符号 A。第二个组没有独特的标志。

    实际上,每个组都可以为每种命令行选项列出四种类型

    • Distinct define flags: 定义编译器符号的标志。
    • 不同的包含目录: 这是用于定义 #include 在哪些目录中查找头文件的标志。 (目录按字母顺序排序,因此依赖于包含路径顺序的罕见错误无法通过这种方式捕获。)
    • 不同的仪器选项: 这用于 coveragescanner 选项。
    • 不同的编译器标志(其他): 用于其他标志。

    在文件组和它们的选项之后,列出了所有源文件共有的命令行选项,并带有前缀 [ALL]

    在我们的示例中,只列出了仪器选项。

Coco v7.2.0©2024 The Qt Company Ltd.
Qt 和相应的标志是芬兰和/或其他国家 Qt Company Ltd. 的商标。所有其他商标均为其各自所有者的财产。