Понимание веток в файлах gcov - PullRequest
7 голосов
/ 15 августа 2011

Я пытаюсь понять вывод инструмента gcov. Запускать без параметров имеет смысл, но я хочу попытаться понять параметры покрытия филиала. К сожалению, трудно понять, что делают ветви и почему они не заняты. Ниже приведен вывод для метода (скомпилируйте с использованием последней сборки LLVM / Clang).

function -[TestCoverageAppDelegate loopThroughArray:] called 5 returned 100% blocks executed 88%
        5:   30:- (NSInteger)loopThroughArray:(NSArray *)array {
        5:   31:    NSInteger i = 0;
       22:   32:    for (NSString *string in array) {
branch  0 taken 0
branch  1 taken 7
        -:   33:        
       22:   34:    }
branch  0 taken 4
branch  1 taken 3
branch  2 taken 0
branch  3 taken 3
        5:   35:    return i;
        -:   36:}

Я выполнил 5 тестов, передав nil, пустой массив, массив с 1 объектом и массив с 2 объектами и массив с 4 объектами. Я могу догадаться, что в первом случае ветвь 1 означает «войти в цикл», но я понятия не имею, что такое ветвь 0. Во втором случае ветвь 0, кажется, снова проходит через цикл, ветвь 1, кажется, завершает цикл, а ветвь 3 - продолжить / выйти из цикла, но я понятия не имею, что такое ветвь 2 или почему / когда она будет выполнена.

Если кто-то знает, как расшифровать информацию о ветке, или знает какую-либо подробную документацию о том, что все это означает, я был бы признателен за помощь.

1 Ответ

3 голосов
/ 15 августа 2011

Gcov работает, инструментируя (при компиляции) каждый базовый блок машинных команд (вы можете подумать об ассемблере). Базовый блок означает линейный фрагмент кода, в котором нет ветвей и меток внутри. Таким образом, если и только если вы начнете запускать базовый блок, вы достигнете конца базового блока. Базовые блоки организованы в CFG (Граф потока управления, представьте его как ориентированный граф), который показывает отношения между базовыми блоками (ребро от V1 до V2 - это V1, называется V2; а V2 вызывается V1). Таким образом, profile-arcs режим компилятора и gcov хотят получить количество выполнений для каждой строки и сделать это путем подсчета основных выполнений блоков. Некоторые ребра в CFG являются инструментальными, а некоторые нет, потому что между базовыми блоками в графе существуют алгебраические отношения.

Ваша конструкция ObjC (for..in) понижена (преобразована при ранней компиляции) в несколько базовых блоков. Итак, gcov видит 4 ветви, потому что видит только пониженные BB. Он ничего не знает об этом понижении, но знает, какая строка соответствует каждой инструкции на ассемблере (это отладочная информация). Итак, ветви - это ребра CFG.

Если вы хотите увидеть базовые блоки, вы должны сделать дамп ассемблера скомпилированной программы или дизассемблировать двоичный файл или сбросить CFG из компилятора. Вы можете сделать это как для profile-arcs, так и для не profile-arcs режимов и сравнить их.

profile-arcs В режиме будет много вызовов и приращений, например, «__llvm_gcov_ctr» или «__llvm_gcda_edge» - это фактическая аппаратура базовых блоков.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...