Spec-Zone.ru › GCC 8

10.2 Вызов gcov

gcov [options] files

gcov принимает следующие параметры:

-a
--all-blocks

Записывает количество выполнений для каждого базового блока. Обычно gcov выводит количество выполнений только для основных блоков строки. С этим параметром вы можете определить, не выполняются ли блоки в одной строке.

-b
--branch-probabilities

Записывает частоту ветвлений в выходной файл и информацию о сводке ветвлений в стандартный вывод. Этот параметр позволяет увидеть, как часто брались каждый ветвь в вашей программе. Неусловные ветви не будут показаны, если не задан параметр -u.

-c
--branch-counts

Записывает частоту ветвлений в виде количества пройденных ветвей, а не процента пройденных ветвей.

-d
--display-progress

Отображает процесс в стандартном выводе.

-f
--function-summaries

Выводит сводки для каждой функции помимо сводки по файлам.

-h
--help

Отображает справку по использованию gcov (в стандартном выводе) и завершает работу без дальнейшей обработки.

-i
--intermediate-format

Выводит файл gcov в формате промежуточного текста, который легко парсится и может использоваться lcov или другими инструментами. На выходе один файл .gcov на каждый файл .gcda. Исходный код не требуется.

Формат промежуточного файла .gcov — обычный текст с одной записью на строку

version:gcc_version
file:source_file_name
function:start_line_number,end_line_number,execution_count,function_name
lcount:line number,execution_count,has_unexecuted_block
branch:line_number,branch_coverage_type

Where the branch_coverage_type is
   notexec (Branch not executed)
   taken (Branch executed and taken)
   nottaken (Branch executed, but not taken)

В файле промежуточного gcov может быть несколько записей file. Все записи, следующие за записью file, относятся к этому исходному файлу до следующей записи file. Если несколько функций начинаются в одной строке, соответствующее значение lcount повторяется несколько раз.

Вот пример, когда -i используется совместно с параметром -b:

version: 8.1.0 20180103
file:tmp.cpp
function:7,7,0,_ZN3FooIcEC2Ev
function:7,7,1,_ZN3FooIiEC2Ev
function:8,8,0,_ZN3FooIcE3incEv
function:8,8,2,_ZN3FooIiE3incEv
function:18,37,1,main
lcount:7,0,1
lcount:7,1,0
lcount:8,0,1
lcount:8,2,0
lcount:18,1,0
lcount:21,1,0
branch:21,taken
branch:21,nottaken
lcount:23,1,0
branch:23,taken
branch:23,nottaken
lcount:24,1,0
branch:24,taken
branch:24,nottaken
lcount:25,1,0
lcount:27,11,0
branch:27,taken
branch:27,taken
lcount:28,10,0
lcount:30,1,1
branch:30,nottaken
branch:30,taken
lcount:32,1,0
branch:32,nottaken
branch:32,taken
lcount:33,0,1
branch:33,notexec
branch:33,notexec
lcount:35,1,0
branch:35,taken
branch:35,nottaken
lcount:36,1,0
-j
--human-readable

Выводит количества в удобочитаемом формате (например, 24k).

-k
--use-colors

Использует цвета для строк кода с нулевым покрытием. Красный цвет используется для неисключительных строк, а циан — для исключительных. Те же цвета используются для базовых блоков с параметром -a.

-l
--long-file-names

Создает длинные имена файлов для включенных исходных файлов. Например, если заголовочный файл x.h содержит код и был включен в файл a.c, то запуск gcov для файла a.c создаст выходной файл с именем a.c##x.h.gcov вместо x.h.gcov. Это может быть полезно, если x.h включен в несколько исходных файлов, и вы хотите увидеть отдельные вклады. Если вы используете параметр ‘-p’, то имена как включающего, так и включаемого файла будут полными путями.

-m
--demangled-names

Отображает разыменованные имена функций в выводе. По умолчанию отображаются имена функций с именами.

-n
--no-output

Не создавать выходной файл gcov.

-o directory|file
--object-directory directory
--object-file file

Укажите либо каталог, содержащий файлы данных gcov, либо имя пути к объекту. Файлы данных .gcno и .gcda ищутся с помощью этого параметра. Если указан каталог, файлы данных находятся в этом каталоге и имеют имя, соответствующее имени входного файла, без расширения. Если указан файл, файлы данных имеют имя, соответствующее этому файлу, без расширения.

-p
--preserve-paths

Сохраняйте полную информацию о пути в именах созданных файлов .gcov. Без этого параметра используется только имя файла. С этим параметром используются все каталоги, при этом символы ‘/’ заменяются символами ‘#’, компоненты каталога . удаляются, а не удаляемые компоненты .. переименовываются в ‘^’. Это полезно, если исходные файлы находятся в нескольких разных каталогах.

-r
--relative-only

Выводить информацию только об исходных файлах с относительным путем (после удаления префикса исходного каталога). Абсолютные пути обычно указывают на системные заголовочные файлы, и покрытие любых встроенных функций в них обычно не представляет интереса.

-s directory
--source-prefix directory

Префикс для имен исходных файлов для удаления при генерации выходных файлов покрытия. Этот параметр полезен при построении в отдельном каталоге, когда путь к каталогу исходных файлов не нужен для определения имен выходных файлов. Обратите внимание, что обнаружение этого префикса выполняется до определения того, является ли исходный файл абсолютным.

-u
--unconditional-branches

При указании вероятностей ветвлений включайте вероятности безусловных ветвлений. Безусловные ветви обычно не представляют интереса.

-v
--version

Отобразить номер версии gcov (в стандартном выводе) и завершить работу без дальнейшей обработки.

-w
--verbose

Выводит подробную информацию, связанную с базовыми блоками и дугами.

-x
--hash-filenames

По умолчанию gcov использует полный путь к исходным файлам для создания имени выходного файла. Это может привести к длинным именам файлов, которые могут переполнить ограничения файловой системы. Этот параметр создает имена в формате source-file##md5.gcov, где source-file — конечная часть имени файла, а md5 — вычисленный по полному разыменованному имени, которое использовалось бы в противном случае.

gcov должен выполняться в текущем каталоге, совпадающем с каталогом, в котором вы вызывали компилятор. В противном случае он не сможет найти исходные файлы. gcov создаёт файлы с именем mangledname.gcov в текущем каталоге. Они содержат информацию о покрытии исходного файла, которому они соответствуют. Один файл .gcov создаётся для каждого исходного (или заголовочного) файла, содержащего код, который был скомпилирован для создания файлов данных. Часть имени выходного файла mangledname обычно просто имя исходного файла, но может быть более сложной, если заданы параметры ‘-l’ или ‘-p’. Обратитесь к этим параметрам за подробностями.

Если вы вызываете gcov с несколькими входными файлами, вклады каждого входного файла суммируются. Обычно вы вызываете его с тем же списком файлов, что и для конечной компоновки вашего исполняемого файла.

Файлы .gcov содержат поля, разделенные символом ‘:’, вместе с исходным кодом программы. Формат

execution_count:line_number:source line text

Дополнительная информация о блоках может следовать за каждой строкой по запросу параметра командной строки. execution_count равен ‘-’ для строк, не содержащих кода. Невыполненные строки отмечаются ‘#####’ или ‘=====’, в зависимости от того, достижимы ли они по неисключительным путям или только по исключительным путям, таким как обработчики исключений C++, соответственно. При использовании параметра ‘-a’ невыполненные блоки отмечаются ‘$$$$$’ или ‘%%%%%’, в зависимости от того, достижим ли базовый блок через неисключительные или исключительные пути. Выполненные базовые блоки, имеющие оператор с нулевым значением execution_count, заканчиваются символом ‘*’ и окрашиваются фиолетовым цветом при использовании параметра -k. Функциональность не поддерживается в Ada.

Обратите внимание, что GCC может полностью удалить тела функций, которые не нужны — например, если они встроены повсюду. Такие функции помечены символом ‘-’, что может быть запутанным. Используйте параметры -fkeep-inline-functions и -fkeep-static-functions, чтобы сохранить эти функции и позволить gcov правильно показать их execution_count.

Некоторые строки информации в начале имеют line_number равное нулю. Эти строки преамбулы имеют вид

-:0:tag:value

Порядок и количество этих строк преамбулы будут расширены по мере развития gcov — не полагайтесь на то, что они останутся неизменными. Используйте tag для поиска определенной строки преамбулы.

Дополнительная информация о блоке имеет вид

tag information

information удобочитаема, но разработана так, чтобы её было достаточно просто анализировать и для машин.

При печати процентов 0% и 100% выводятся только тогда, когда значения точно равны 0% и 100% соответственно. Другие значения, которые обычно округляются до 0% или 100%, вместо этого выводятся как ближайшее неграничное значение.

При использовании gcov, необходимо сначала скомпилировать программу с двумя специальными параметрами GCC: ‘-fprofile-arcs -ftest-coverage’. Это сообщает компилятору о генерации дополнительной информации, необходимой gcov (по существу, графа потока программы), а также включает дополнительный код в объектные файлы для создания дополнительной информации о профилировании, необходимой gcov. Эти дополнительные файлы помещаются в каталог, где находится объектный файл.

Запуск программы приведет к генерации выходных данных профиля. Для каждого исходного файла, скомпилированного с параметром -fprofile-arcs, в каталог объектного файла будет помещен соответствующий файл .gcda.

Запуск gcov с именами исходных файлов вашей программы в качестве аргументов теперь выведет список кода вместе с частотой выполнения каждой строки. Например, если ваша программа называется tmp.cpp, вот что вы видите при использовании базового gcov механизма:

$ g++ -fprofile-arcs -ftest-coverage tmp.cpp
$ a.out
$ gcov tmp.cpp -m
File 'tmp.cpp'
Lines executed:92.86% of 14
Creating 'tmp.cpp.gcov'

Файл tmp.cpp.gcov содержит вывод от gcov. Вот пример:

-:    0:Source:tmp.cpp
        -:    0:Graph:tmp.gcno
        -:    0:Data:tmp.gcda
        -:    0:Runs:1
        -:    0:Programs:1
        -:    1:#include <stdio.h>
        -:    2:
        -:    3:template<class T>
        -:    4:class Foo
        -:    5:{
        -:    6:  public:
       1*:    7:  Foo(): b (1000) {}
------------------
Foo<char>::Foo():
    #####:    7:  Foo(): b (1000) {}
------------------
Foo<int>::Foo():
        1:    7:  Foo(): b (1000) {}
------------------
       2*:    8:  void inc () { b++; }
------------------
Foo<char>::inc():
    #####:    8:  void inc () { b++; }
------------------
Foo<int>::inc():
        2:    8:  void inc () { b++; }
------------------
        -:    9:
        -:   10:  private:
        -:   11:  int b;
        -:   12:};
        -:   13:
        -:   14:template class Foo<int>;
        -:   15:template class Foo<char>;
        -:   16:
        -:   17:int
        1:   18:main (void)
        -:   19:{
        -:   20:  int i, total;
        1:   21:  Foo<int> counter;
        -:   22:
        1:   23:  counter.inc();
        1:   24:  counter.inc();
        1:   25:  total = 0;
        -:   26:
       11:   27:  for (i = 0; i < 10; i++)
       10:   28:    total += i;
        -:   29:
       1*:   30:  int v = total > 100 ? 1 : 2;
        -:   31:
        1:   32:  if (total != 45)
    #####:   33:    printf ("Failure\n");
        -:   34:  else
        1:   35:    printf ("Success\n");
        1:   36:  return 0;
        -:   37:}

Обратите внимание, что строка 7 показана в отчёте несколько раз. Первое появление представляет общее количество выполнений строки, а следующие два относятся к экземплярам конструкторов класса Foo. Как вы также можете видеть, строка 30 содержит некоторые невыполненные базовые блоки, и поэтому счёт выполнения имеет символ звёздочки.

При использовании параметра -a вы получите отдельные счётчики блоков, и вывод будет выглядеть так:

-:    0:Source:tmp.cpp
        -:    0:Graph:tmp.gcno
        -:    0:Data:tmp.gcda
        -:    0:Runs:1
        -:    0:Programs:1
        -:    1:#include <stdio.h>
        -:    2:
        -:    3:template<class T>
        -:    4:class Foo
        -:    5:{
        -:    6:  public:
       1*:    7:  Foo(): b (1000) {}
------------------
Foo<char>::Foo():
    #####:    7:  Foo(): b (1000) {}
------------------
Foo<int>::Foo():
        1:    7:  Foo(): b (1000) {}
------------------
       2*:    8:  void inc () { b++; }
------------------
Foo<char>::inc():
    #####:    8:  void inc () { b++; }
------------------
Foo<int>::inc():
        2:    8:  void inc () { b++; }
------------------
        -:    9:
        -:   10:  private:
        -:   11:  int b;
        -:   12:};
        -:   13:
        -:   14:template class Foo<int>;
        -:   15:template class Foo<char>;
        -:   16:
        -:   17:int
        1:   18:main (void)
        -:   19:{
        -:   20:  int i, total;
        1:   21:  Foo<int> counter;
        1:   21-block  0
        -:   22:
        1:   23:  counter.inc();
        1:   23-block  0
        1:   24:  counter.inc();
        1:   24-block  0
        1:   25:  total = 0;
        -:   26:
       11:   27:  for (i = 0; i < 10; i++)
        1:   27-block  0
       11:   27-block  1
       10:   28:    total += i;
       10:   28-block  0
        -:   29:
       1*:   30:  int v = total > 100 ? 1 : 2;
        1:   30-block  0
    %%%%%:   30-block  1
        1:   30-block  2
        -:   31:
        1:   32:  if (total != 45)
        1:   32-block  0
    #####:   33:    printf ("Failure\n");
    %%%%%:   33-block  0
        -:   34:  else
        1:   35:    printf ("Success\n");
        1:   35-block  0
        1:   36:  return 0;
        1:   36-block  0
        -:   37:}

В этом режиме каждый базовый блок отображается только на одной строке – последней строке блока. Многострочный блок будет учитываться только в счёт выполнения последней строки, а другие строки не будут показаны как содержащие код, если предыдущие блоки не заканчиваются на этих строках. Общее количество выполнений строки отображается, а последующие строки показывают счёт выполнения отдельных блоков, которые заканчиваются на этой строке. После каждого блока будут показаны счёт ветвлений и вызовов блока, если используется опция -b.

Из-за того, как GCC инструментирует вызовы, счёт вызовов может отображаться после строки без отдельных блоков. Как видно, строка 33 содержит базовый блок, который не был выполнен.

Когда вы используете опцию -b, ваш вывод выглядит так:

-:    0:Source:tmp.cpp
        -:    0:Graph:tmp.gcno
        -:    0:Data:tmp.gcda
        -:    0:Runs:1
        -:    0:Programs:1
        -:    1:#include <stdio.h>
        -:    2:
        -:    3:template<class T>
        -:    4:class Foo
        -:    5:{
        -:    6:  public:
       1*:    7:  Foo(): b (1000) {}
------------------
Foo<char>::Foo():
function Foo<char>::Foo() called 0 returned 0% blocks executed 0%
    #####:    7:  Foo(): b (1000) {}
------------------
Foo<int>::Foo():
function Foo<int>::Foo() called 1 returned 100% blocks executed 100%
        1:    7:  Foo(): b (1000) {}
------------------
       2*:    8:  void inc () { b++; }
------------------
Foo<char>::inc():
function Foo<char>::inc() called 0 returned 0% blocks executed 0%
    #####:    8:  void inc () { b++; }
------------------
Foo<int>::inc():
function Foo<int>::inc() called 2 returned 100% blocks executed 100%
        2:    8:  void inc () { b++; }
------------------
        -:    9:
        -:   10:  private:
        -:   11:  int b;
        -:   12:};
        -:   13:
        -:   14:template class Foo<int>;
        -:   15:template class Foo<char>;
        -:   16:
        -:   17:int
function main called 1 returned 100% blocks executed 81%
        1:   18:main (void)
        -:   19:{
        -:   20:  int i, total;
        1:   21:  Foo<int> counter;
call    0 returned 100%
branch  1 taken 100% (fallthrough)
branch  2 taken 0% (throw)
        -:   22:
        1:   23:  counter.inc();
call    0 returned 100%
branch  1 taken 100% (fallthrough)
branch  2 taken 0% (throw)
        1:   24:  counter.inc();
call    0 returned 100%
branch  1 taken 100% (fallthrough)
branch  2 taken 0% (throw)
        1:   25:  total = 0;
        -:   26:
       11:   27:  for (i = 0; i < 10; i++)
branch  0 taken 91% (fallthrough)
branch  1 taken 9%
       10:   28:    total += i;
        -:   29:
       1*:   30:  int v = total > 100 ? 1 : 2;
branch  0 taken 0% (fallthrough)
branch  1 taken 100%
        -:   31:
        1:   32:  if (total != 45)
branch  0 taken 0% (fallthrough)
branch  1 taken 100%
    #####:   33:    printf ("Failure\n");
call    0 never executed
branch  1 never executed
branch  2 never executed
        -:   34:  else
        1:   35:    printf ("Success\n");
call    0 returned 100%
branch  1 taken 100% (fallthrough)
branch  2 taken 0% (throw)
        1:   36:  return 0;
        -:   37:}

Для каждой функции печатается строка, показывающая, сколько раз функция вызывалась, сколько раз она возвращалась и какой процент блоков функции был выполнен.

Для каждого базового блока после последней строки базового блока печатается строка, описывающая ветвление или вызов, которые завершают базовый блок. Может быть несколько ветвлений и вызовов, перечисленных для одной строки исходного кода, если существует несколько базовых блоков, которые заканчиваются на этой строке. В этом случае ветвлениям и вызовам присваиваются номера. Нет простого способа сопоставить эти ветвления и вызовы с конструкциями исходного кода. Однако, как правило, ветвление или вызов с наименьшим номером соответствует левой конструкции в строке исходного кода.

Для ветвления, если оно было выполнено хотя бы один раз, будет напечатан процент, показывающий, сколько раз ветвление было взято, делённое на количество раз, когда ветвление было выполнено. В противном случае печатается сообщение «никогда не выполнено».

Для вызова, если он был выполнен хотя бы один раз, будет напечатан процент, показывающий, сколько раз вызов вернул, делённое на количество раз, когда вызов был выполнен. Это обычно будет 100%, но может быть меньше для функций, которые вызывают exit или longjmp, и, таким образом, могут не возвращаться каждый раз, когда они вызываются.

Счёты выполнения являются кумулятивными. Если пример программы будет повторён без удаления файла .gcda, счёт количества раз, когда каждая строка в исходном коде была выполнена, будет добавлен к результатам предыдущих запусков. Это может быть полезно в нескольких отношениях. Например, это может быть использовано для накопления данных на протяжении нескольких запусков программы в рамках комплекта проверки, или для предоставления более точной долгосрочной информации для большого числа запусков программы.

Данные в файлах .gcda сохраняются непосредственно перед завершением программы. Для каждого файла исходного кода, скомпилированного с -fprofile-arcs, код профилирования сначала пытается прочитать существующий файл .gcda; если файл не соответствует исполняемому файлу (отличающееся количество счётов базовых блоков), он проигнорирует содержимое файла. Затем он добавляет новые счёт выполнения и, наконец, записывает данные в файл.

Далее: Gcov и оптимизация, Предыдущее: Введение в Gcov, Вверх: Gcov [Оглавление][Индекс]

© Free Software Foundation
Licensed under the GNU Free Documentation License, Version 1.3.
https://gcc.gnu.org/onlinedocs/gcc-8.5.0/gcc/Invoking-Gcov.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API