2016-05-20 91 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的標記幾乎所有的文件爲不可執行的行,但跟蹤線82的3個執行:一個單一的右括號。

這對我來說沒有任何意義,我也無法在網絡上找到有關此問題的任何信息。任何幫助將不勝感激。

回答

1

下面是對gcov的行爲(以及相關的軟件,如gcovr和LCOV)粗略流程圖:

gcov data flow

圖:gcov的數據流

當編譯器(GCC )生成目標代碼,並被要求插入coverage/profiling儀器,它會做兩件額外的事情:

  • 該對象代碼可用於在執行時將覆蓋率度量標準寫入.gcda文件。
  • 生成一個.gcno文件,它描述了目標代碼的結構。

gcov實用程序然後解析.gcda和.gcno文件以計算覆蓋率度量。對於註釋的源報告,它也讀取源文件。

因爲它是編譯器確定目標代碼的哪一部分與特定行相對應,所以顯示的報告是正確的:該行不存在。更確切地說:這些源代碼行沒有生成目標代碼。這通常是預期的行爲,因爲許多源代碼行只是編譯時聲明。

在你的情況你有一個C++類inline functions(類定義內的任何函數定義都隱式內聯)。編譯器不需要爲未使用的內聯函數生成代碼。如果使用非內聯函數,這將會不同,即在頭文件中聲明函數並在.cpp文件中提供實現。

那麼最後三個執行結束括號是怎麼回事?編譯器通常需要發出一些與靜態對象的初始化和清理相關的代碼。這段代碼並不真正與特定的行關聯,因此作爲編譯單元中最後一行的一部分出現。