Какие ветви в конце этой функции. Как я мог их покрыть?
Вы наблюдаете сгенерированный gcc код для уничтожения статических (глобальных) переменных продолжительности хранения.
Ваше покрытие показывает, что функция foo
был введен три раза, однако счетчик в конце области показывает, что код был выполнен восемь раз, включая ветви, о которых вы спрашиваете.
Теперь вы должны учесть, что компилятор помещает заголовочный файл в модуль перевода и что gcov не видит ваш код в точности так, как он есть, а скорее как граф управляющего потока инструкции по сборке с ветвлением в качестве краев графа.
Таким образом, «конец foo
область «в выводе HTML lcov на самом деле не конец 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
У меня была такая же проблема с концевыми скобками, которые не были включены в пустую функцию;
Я нашел два обходных пути:
сначала добавьте конечную скобку к последней строке вызова функции, чтобы они не отображались как отдельная строка
второе и лучшее: добавить случайный «возврат»; в конце функции для принудительного выполнения кода
Как супер упрощенный ответ, ветви означают 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) новых ветви для покрытия. Два вложенных, родительский вложенный и скрытый другой.
В общем, имейте в виду покрытие веток, речь идет о покрытии условных высказываний.