12

在此处输入图像描述

这个函数末尾的分支是什么。我怎么能覆盖它们?

4

3 回答 3

15

您正在观察 gcc 生成的代码以破坏静态存储持续时间(全局)变量。

您的报道显示该函数foo已被输入了 3 次,但范围末尾附近的计数器显示代码已执行 8 次,包括您查询的分支。

现在您必须考虑编译器将头文件放在翻译单元中,并且 gcov 不会完全按照原样查看您的代码,而是将其视为汇编指令的控制流图,其中分支作为图的边缘。

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

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

请注意,您可能已经包含了全局变量,或者您可能没有 - 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
于 2014-01-01T12:51:07.680 回答
0

我对 void 函数未涵盖的端括号也有同样的问题;

我找到了两种解决方法:

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

  • 第二个和更好:添加随机“return;” 在函数末尾强制执行代码

于 2015-11-10T15:28:56.270 回答
-3

作为一个超级简单的答案,分支表示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) 新分支来覆盖。两个嵌套,嵌套的父级和隐藏的else。

总体记住覆盖分支,就是覆盖条件语句。

于 2016-12-15T15:23:38.387 回答