LCOV在函数末尾分支

时间:2014-01-01 07:12:32

标签: c++ gcov lcov

enter image description here

此功能结束时的分支是什么。我怎么能掩盖他们?

3 个答案:

答案 0 :(得分:10)

您正在观察gcc生成的代码,用于销毁静态存储持续时间(全局)变量。

您的报道显示函数foo已输入三次,但是示波器末尾附近的计数器显示代码已执行八次,包括您查询的分支。

现在你必须考虑编译器将头文件放在转换单元中并且gcov没有完全看到你的代码,而是作为汇编指令的控制流图,其中分支作为图的边缘

因此,lcov html输出中的“foo范围的结尾”实际上并不是foo方法范围的结束,而是整个foo之后包含的所有内容。翻译单元,包括销毁在头文件中声明的全局变量。

标题本身尚未包含在问题中,但即使是gcc生成的最基本的__static_initialization_and_destruction程序集也包含了许多分支。

请注意,您可能已包含全局变量,或者您可能没有 - gcc仍可能为每个翻译单元生成此代码。


查看gcov的基础输出:

function _Z3fooi called 1 returned 100% blocks executed 50%
        1:    4:int foo(int x) {
        1:    5:    if (x==1) {
branch  0 taken 0% (fallthrough)
branch  1 taken 100%
    #####:    6:        std::cout << "foo" << std::endl;
call    0 never executed
call    1 never executed
    #####:    7:        return 0;
        -:    8:    }
        1:    9:    return 1;
function _GLOBAL__sub_D__Z3fooi called 1 returned 100% blocks executed 100%
function _GLOBAL__sub_I__Z3fooi called 1 returned 100% blocks executed 100%
function _Z41__static_initialization_and_destruction_0ii called 2 returned 100% blocks executed 100%
        6:   10:}
call    0 returned 100%
call    1 returned 100%
branch  2 taken 50% (fallthrough)
branch  3 taken 50%
branch  4 taken 100% (fallthrough)
branch  5 taken 0%
        -:   11:

看看生成的装配,修剪以澄清要点:

        ...
        ret
        .seh_endproc
        .def    _Z41__static_initialization_and_destruction_0ii;        .scl    3;      .type   32;     .endef
        .seh_proc       _Z41__static_initialization_and_destruction_0ii
_Z41__static_initialization_and_destruction_0ii:
.LFB978:
        ...
        mov     QWORD PTR __gcov0._Z41__static_initialization_and_destruction_0ii[rip], rax
        cmp     DWORD PTR 16[rbp], 1
        jne     .L5                                 <-- BRANCH
        mov     rax, QWORD PTR __gcov0._Z41__static_initialization_and_destruction_0ii[rip+8]
        add     rax, 1
        mov     QWORD PTR __gcov0._Z41__static_initialization_and_destruction_0ii[rip+8], rax
        cmp     DWORD PTR 24[rbp], 65535
        jne     .L5                                 <-- BRANCH
        ...
.L5:
        cmp     DWORD PTR 16[rbp], 0
        je      .L6                                 <-- BRANCH

答案 1 :(得分:0)

我在端部括号中遇到了同样的问题,这个问题没有包含在void函数中;

我找到了两个解决方法:

  • 首先将endbracket添加到最后一个powercall行,这样它们就不会显示为单独的行

  • 第二个更好:添加随机&#34;返回;&#34;在函数结束时强制执行代码

答案 2 :(得分:-1)

作为超级简单的答案,分支表示 IF / ELSE分支。所以对于每个if / else都有两个新的分支(应该被覆盖);如果嵌套,则以指数方式增长。

function twoNewBranches() {
  if () {
    // code
  } else {
    // code
  }
}

function twoNewBranchesNotAparent() {
  if () {
    // code
  }
}

function fourNewBranches() {
  if () {
    if () {
      // code
    } else {
      // code
    }
  }
}

•第一个函数 twoNewBranches 创建了两个需要覆盖的新分支

•第二个函数 twoNewBranchesNotAparent 也会创建两个新分支,因为您仍然必须覆盖不满足if语句的测试

•第三个函数 fourNewBranches 创建四个(2 ^ 2 = 4)个新分支来覆盖。两个嵌套,嵌套的父级和隐藏的其他。

总体上要记住覆盖分支,是关于覆盖条件语句。