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.
© Free Software Foundation
Licensed under the GNU Free Documentation License, Version 1.3.
https://gcc.gnu.org/onlinedocs/gcc-4.9.4/gcc/Gcov-and-Optimization.html