2016-05-20 59 views
5

Sto utilizzando gcov per la copertura del test delle metriche su una libreria C++ a cui contribuisco. Per qualche ragione, gcov non riconosce le righe in molti dei file come eseguibili. Su 160-alcune linee in un dato file dirà che 40 di esse sono eseguibili. Ad esempio:gcov ignorando le righe nel file sorgente

  -: 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 

Qui, gcov segna quasi tutte le righe nel file come non eseguibile, ma tracce 3 esecuzioni di linea 82: una singola staffa di chiusura.

Questo non ha senso per me e non sono stato in grado di trovare nulla su questo problema sul web. Qualsiasi aiuto sarebbe molto apprezzato.

risposta

1

Ecco un diagramma di flusso di massima per il comportamento di gcov (e relativo software come gcovr e lcov):

gcov data flow

Figura: dati gcov flusso

Quando il compilatore (GCC) genera il codice oggetto e gli è stato chiesto di inserire la strumentazione di copertura/profilazione, fa due cose aggiuntive:

  • Il codice oggetto è strumentato per scrivere metriche di copertura in un file .gcda al momento dell'esecuzione.
  • Viene generato un file .gcno, che descrive la struttura del codice oggetto.

L'utilità gcov analizza quindi i file .gcda e .gcno per calcolare le metriche di copertura. Per il report sorgente annotato, legge anche il file sorgente.

Poiché è il compilatore che determina quale parte del codice oggetto corrisponde a una particolare linea, il report che hai mostrato è corretto: quella linea non esiste. Più precisamente: nessun codice oggetto è stato generato per quelle linee di codice sorgente. Questo è generalmente il comportamento previsto, dal momento che molte righe di codice sorgente sono solo dichiarazioni in fase di compilazione.

Nel tuo caso si dispone di una classe C++ con inline functions (qualsiasi definizione di funzione all'interno di una definizione di classe è implicitamente in linea). Il compilatore non ha bisogno di generare codice per funzioni inline che non vengono utilizzate. Ciò sarebbe diverso se si utilizzano funzioni non inline, ovvero dichiarare le funzioni in un file di intestazione e fornire implementazioni in un file .cpp.

Allora, che succede con le tre esecuzioni di una parentesi di chiusura? Il compilatore ha spesso bisogno di emettere un codice associato all'inizializzazione e alla pulizia degli oggetti statici. Questo codice non è realmente associato a una linea specifica e pertanto appare come parte dell'ultima riga della tua unità di compilazione.

Problemi correlati