2016-05-20 7 views
5

Я использую gcov для покрытия метрического тестирования в библиотеке C++, в которую я вношу свой вклад. По какой-то причине gcov не распознает строки во многих файлах как исполняемые. Из 160-некоторых строк в данном файле будет сказано, что 40 из них исполняются. Например:gcov игнорирование строк в исходном файле

  -: 0:Source:../evo/NK.h 
    -: 0:Graph:test_driver.gcno 
    -: 0:Data:test_driver.gcda 
    -: 0:Runs:1 
    -: 0:Programs:1 
    -: 1:// This file is part of Empirical, https://github.com/devosoft/Empirical 
    -: 2:// Copyright (C) Michigan State University, 2016. 
    -: 3:// Released under the MIT Software license; see doc/LICENSE 
    -: 4:// 
    -: 5:// 
    -: 6:// This file provides code to build NK-based algorithms. 
    -: 7: 
    -: 8:#ifndef EMP_EVO_NK_H 
    -: 9:#define EMP_EVO_NK_H 
    -: 10: 
    -: 11:#include <array> 
    -: 12: 
    -: 13:#include "../tools/BitVector.h" 
    -: 14:#include "../tools/const_utils.h" 
    -: 15:#include "../tools/Random.h" 
    -: 16:#include "../tools/vector.h" 
    -: 17: 
    -: 18:namespace emp { 
    -: 19:namespace evo { 
    -: 20: 
    -: 21: class NKLandscape { 
    -: 22: private: 
    -: 23: const uint32_t N; 
    -: 24: const uint32_t K; 
    -: 25: const uint32_t state_count; 
    -: 26: const uint32_t total_count; 
    -: 27: emp::vector< emp::vector<double> > landscape; 
    -: 28: 
    -: 29: public: 
    -: 30: NKLandscape() = delete; 
    -: 31: NKLandscape(const NKLandscape &) = delete; 
    -: 32: NKLandscape(int _N, int _K, emp::Random & random) 
    -: 33:  : N(_N), K(_K) 
    -: 34:  , state_count(emp::constant::IntPow<uint32_t>(2,K+1)) 
    -: 35:  , total_count(N * state_count) 
    -: 36:  , landscape(N) 
    -: 37: { 
    -: 38:  for (auto & ltable : landscape) { 
    -: 39:  ltable.resize(state_count); 
    -: 40:  for (double & pos : ltable) { 
    -: 41:   pos = random.GetDouble(); 
    -: 42:  } 
    -: 43:  } 
    -: 44: } 
    -: 45: ~NKLandscape() { ; } 
    -: 46: NKLandscape & operator=(const NKLandscape &) = delete; 
    -: 47: 
    -: 48: int GetN() const { return N; } 
    -: 49: int GetK() const { return K; } 
    -: 50: int GetStateCount() const { return state_count; } 
    -: 51: int GetTotalCount() const { return total_count; } 
    -: 52: 
    -: 53: double GetFitness(int n, uint32_t state) const { 
    -: 54:  emp_assert(state < state_count, state, state_count); 
    -: 55:  return landscape[n][state]; 
    -: 56: } 
    -: 57: double GetFitness(std::vector<uint32_t> states) const { 
    -: 58:  emp_assert(states.size() == N); 
    -: 59:  double total = landscape[0][states[0]]; 
    -: 60:  for (int i = 1; i < N; i++) total += GetFitness(i,states[i]); 
    -: 61:  return total; 
    -: 62: } 
    -: 63: double GetFitness(BitVector genome) const { 
    -: 64:  emp_assert(genome.GetSize() == N); 
    -: 65: 
    -: 66:  // Use a double-length genome to easily handle wrap-around. 
    -: 67:  genome.Resize(N*2); 
    -: 68:  genome |= (genome << N); 
    -: 69: 
    -: 70:  double total = 0.0; 
    -: 71:  uint32_t mask = emp::constant::MaskLow<uint32_t>(K+1); 
    -: 72:  for (int i = 0; i < N; i++) { 
    -: 73:  const uint32_t cur_val = (genome >> i).GetUInt(0) & mask; 
    -: 74:   const double cur_fit = GetFitness(i, cur_val); 
    -: 75:  total += cur_fit; 
    -: 76:  } 
    -: 77:  return total; 
    -: 78: } 
    -: 79: }; 
    -: 80: 
    -: 81:} 
    3: 82:} 
    -: 83: 
    -: 84:#endif 

Здесь gcov отмечает почти все строки в файле как неисполняемые, но отслеживает 3 расстрелы линии 82: один закрывающую скобку.

Это не имеет никакого смысла для меня, и я не смог найти что-либо об этой проблеме в Интернете. Любая помощь будет принята с благодарностью.

ответ

1

Вот грубый блок-схема алгоритма поведения gcov (и соответствующего программного обеспечения, как gcovr и lcov):

gcov data flow

Рисунок: gcov поток данных

Когда компилятор (GCC) генерирует объектный код, и ему было предложено вставить оборудование для покрытия/профилирования, оно делает две дополнительные вещи:

  • Код объекта предназначен для записи метрик покрытия в файл .gcda после его выполнения.
  • Создается файл .gcno, который описывает структуру объектного кода.

Затем утилита gcov анализирует файлы .gcda и .gcno для вычисления показателей покрытия. Для аннотированного исходного отчета он также считывает исходный файл.

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

В вашем случае у вас есть класс C++ с inline functions (любые определения функций в определении класса неявно встроены). Компилятору не нужно генерировать код для встроенных функций, которые не используются. Это было бы иначе, если вы используете не-встроенные функции, то есть объявляете функции в файле заголовка и предоставляете реализации в файле .cpp.

Итак, что случилось с тремя исполнением закрывающей скобки? Компилятор часто должен испускать некоторый код, связанный с инициализацией и очисткой статических объектов. Этот код на самом деле не связан с определенной строкой и поэтому отображается как часть последней строки в вашем блоке компиляции.

Смежные вопросы