Spec-Zone.ru › GCC 8

10.3 Использование gcov с оптимизацией GCC

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

if (a != b)
  c = 1;
else
  c = 0;

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

100:   12:if (a != b)
100:   13:  c = 1;
100:   14:else
100:   15:  c = 0;

Вывод показывает, что этот блок кода, объединенный оптимизацией, был выполнен 100 раз. В некотором смысле этот результат верен, поскольку была только одна инструкция, представляющая все четыре строки. Однако вывод не указывает, сколько раз результат был 0, и сколько раз результат был 1.

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

Если функция не встраивается, компилятор должен выдать внестрочную копию функции в любой объектный файл, который её нуждается. Если fileA.o и fileB.o оба содержат внестрочные тела определенной встраиваемой функции, они также будут содержать счетчики покрытия для этой функции. Когда fileA.o и fileB.o связываются вместе, компоновщик на многих системах выберет одно из этих внестрочных тел для всех вызовов этой функции и удалит или проигнорирует остальные. К сожалению, он не удалит счетчики покрытия для неиспользуемого тела функции. Таким образом, при инструментировании все, кроме одного использования этой функции, покажут нулевые значения счетчиков.

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

Для долго работающих приложений можно использовать средства __gcov_reset и __gcov_dump для ограничения сбора профиля областью программы, представляющей интерес. Вызов __gcov_reset(void) обнулит все счетчики профиля, а вызов __gcov_dump(void) приведет к выводу собранной профильной информации в файлы выходных данных .gcda. Инструментированные приложения используют статический деструктор с приоритетом 99 для вызова функции __gcov_dump. Таким образом, __gcov_dump выполняется после всех пользовательских статических деструкторов, а также обработчиков, зарегистрированных с atexit. Если исполняемый файл загружает динамическую общую библиотеку через функцию dlopen, требуется -Wl,--dynamic-list-data для вывода всех данных профиля.

Далее: Файлы данных 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/Gcov-and-Optimization.html

Spec-Zone.ru

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