Este tutorial descreve a ferramenta de cobertura de código fonte Gcov e como utilizá-la para analisar programas e descobrir partes que não foram testadas. O Gcov anota o código fonte de um programa e gera contagens dos números de vezes que cada linha foi executada.

Renato Stoffalette Joao, Software Engineer, IBM Systems & Technology Group, IBM

Renato Stoffalette Joao é Engenheiro de Software no Linux Technology Center (LTC) da IBM Brasil. Seu trabalho no LTC consiste em interações com diversas comunidades de código aberto Linux e desenvolvimento de extensões da plataforma Eclipse IDE usando a linguagem Java. É bacharel em Ciência da Computação pela Universidade Estadual Paulista (UNESP) e mestrando pela Universidade Federal do ABC (UFABC).



10/Out/2012

Introdução ao Gcov

A cobertura de código fonte é uma medida utilizada em testes de software e foi uma das primeiras técnicas de testes de software criadas. A primeira referência a esta técnica foi feita por Miller e Maloney em 1963 [1].

O conjunto de ferramentas GCC (GNU Compiler Collection) [2] traz dentre outras ferramentas, o Gcov, que realiza justamente testes de cobertura de código fonte .

O Gcov realiza análise de código fonte e gera uma contagem do número exato de vezes que cada linha de código é executada em um programa. Ele produz uma cópia idêntica do código fonte do programa analisado com as linhas anotadas com as frequências de execuções.

Com o uso do Gcov é possível obter informações sobre a frequência com que cada linha de código é executada. Com este tipo de informação é possível analisar quais partes de um programa devem ser otimizadas.


Executando o Gcov

O Gcov funciona apenas em programas compilados com o compilador GCC.

Antes de executar o Gcov, é preciso compilar o programa utilizando o GCC com dois parâmetros especiais, -fprofile-arcs e -ftest-coverage, que irão orientar o compilador a criar informações requeridas pelo Gcov. Estas opções são passadas ao compilador no momento que o programa está sendo compilado.

A opção -ftest-coverage adiciona instruções, no binário, para contagem do número de vezes que cada linha de código é executada.

A opção -fprofile-arcs adiciona código instrumentado para cada ramificação do programa executado. A instrumentação das ramificações registra a frequência dos caminhos tomados pelos laços e pelas sentenças condicionais.

Além das opções acima, para utilizar o Gcov é preciso compilar seu programa sem otimização pois a otimização de código pode não fornecer informações necessárias para a análise de partes do programa que estão utilizando grande quantidade de tempo computacional. E como o Gcov acumula as frequências por linha de código, ele funciona melhor em um programa com um estilo de programação com apenas uma sentença de código por linha.

Veja um exemplo de como compilar um código fonte em C utilizando o GCC apropriadamente.

Este comando irá compilar seu código fonte e criar um programa executável capaz de produzir as informações necessárias para análise com o Gcov.

#gcc -g -fprofile-arcs -ftest-coverage código_fonte.c -o  programa

Note que ao término da compilação será criado um arquivo com o mesmo nome do código fonte porém com a extensão .gcno.

O arquivo com extensão .gcno é criado toda vez que um código fonte é compilado com a opção -ftest-coverage. Este arquivo contém informação para reconstruir os grafos de transições dos blocos de código e atribuir números nas linhas de código dos blocos.

Dado o fim do processo de compilação, o programa precisa ser executado, pois somente após a execução é possível obter informações sobre a cobertura do código fonte, ou seja a frequência de execução dos métodos e rotinas do seu programa.

Seu programa deverá ser executado naturalmente como de costume e produzir as saídas normalmente.

Ao término de execução do programa serão criados arquivos com a extensão .gcda referentes a cada código fonte compilado com a opção -fprofile-arcs.

Um arquivo .gcda é criado para cada arquivo objeto compilado com esta opção. Ele contém a contagem das transições dos arcos dos grafos.

O Gcov utiliza dois tipos de arquivos para análise. Os nomes destes arquivos são derivados do nome original do código fonte adicionado do sufixo .gcno ou .gcda.

Todos estes arquivos são colocados no mesmo diretório do arquivo objeto e contém dados em um formato independente da plataforma de onde foram gerados.

O Gcov precisa ser executado dentro do mesmo diretório no qual o compilador foi executado ou ele não será capaz de localizar os códigos fontes do seu programa.

O formato padrão para execução do Gcov é o seguinte:

# gcov OPÇÕES CÓDIGO_FONTE

As opções disponíveis para executar o Gcov são vistas na Tabela 1 abaixo.

-h, --help Mostra ajuda sobre como utilizar o Gcov.
-v, --version Mostra a versão atual do Gcov.
-a, --all-blocks Escreve uma contagem individual para cada bloco de código. Normalmente o Gcov mostra a contagem somente para os blocos principais, mas com esta opção você pode determinar se blocos dentro de uma única linha não estão sendo executados.
-b,--branch-probabilitiesGrava frequências das ramificações no arquivo e escreve um resumo da ramificação na saída padrão. Esta opção permite que você veja a frequência com que cada ramificação do seu programa foi executada.
-c, --branch-counts Mostra as frequências de cada ramificação em números ao invés das porcentagens.
-n, --no-output Não cria um arquivo gcov de saída.
-l, --long-file-namesCria nomes estendidos para os códigos fontes incluídos. Ex: Se o cabeçalho x.h foi incluído no arquivo a.c então executar o gcov no arquivo a.c irá produzir um arquivo de saída chamado a.c##x.h.gcov.
-p, --preserve-paths Esta opção preserva informação sobre o caminho completo no nome dos arquivos .gcov gerados.
-f, --function-summaries Esta opção mostra resumos para cada função.
-o diretorio | arquivo
--object-directory diretorio
--object-file arquivo
Especifica ou o diretório contendo os arquivos do gcov ou o nome do caminho do arquivo objeto.
-u, --unconditional-branches Mostra contagens para desvios não condicionais.

Quando o Gcov terminar sua execução, este irá criar um arquivo com anotações nas linhas do código fonte do programa analisado. Este arquivo irá possuir o mesmo nome do código fonte analisado, porém, com a extensão .gcov.


Interpretando os Resultados

O Gcov geralmente produz arquivos de saída com a extensão .gcov no diretório onde está sendo executado. Um arquivo com extensão .gcov é criado para cada código fonte compilado compilado com as opções -fprofile-arcs e -ftest-coverage.

Note que caso o Gcov seja executado com múltiplos arquivos de entrada todas as suas saídas serão somadas.

Quando o Gcov for executado, você irá visualizar uma mensagem semelhante a da imagem abaixo informando a quantidade de linhas executadas do seu código fonte e a criação do arquivo de resultado do Gcov.

Clique aqui para ver lista de códigos

 $ gcov -c gcovTest.c  $ gcov -c gcovTest.c  File 'gcovTest.c'  Lines executed:87.50% of 8  gcovTest.c:creating 'gcovTest.c.gcov'

Assim, como dito previamente, o resultado desta execução irá produzir um arquivo com o mesmo nome do arquivo de código fonte acrescido da extensão .gcov. Neste caso o arquivo produzido chama-se gcovTest.c.gcov. E o seu conteúdo pode ser visto abaixo.

            -:    0:Source:gcovTest.c 
        -:    0:Graph:gcovTest.gcno 
        -:    0:Data:gcovTest.gcda 
        -:    0:Runs:1 
        -:    0:Programs:1 
        -:    1:#include <stdio.h> 
        -:    2: 
        1:    3:int main (void) 
        -:    4:{ 
        -:    5: int i, total; 
        1:    6: total = 0; 
        21:    7: for (i = 0; i < 20; i++){ 
        20:    8:      total += i; 
        20:    9:      if (total != 50){ 
        20:   10:         printf ("Falha\n"); 
         -:   11:       }else{ 
     #####:   12:         printf ("Sucesso\n"); 
         -:   13:        } 
         -:   14:     } 
         1:   15:  return 0; 
         -:   16:}

O arquivo gcovTest.c.gcov contém dois campos delimitados pelo símbolo ":" acompanhado do código-fonte do programa.

O conteúdo padrão dos arquivos de extensão .gcov contém os seguintes campos:

contagem_de_execuções : número_da_linha : código_fonte

O campo contagem_de_execuções representa as frequências de execução por linha de código. Ela pode conter o símbolo “-” para linhas que não contém nenhum código ou “#####” para as linhas de código que não foram executadas.

A contagem realizada das execuções do programa é cumulativa. E caso o programa em análise seja executado novamente sem que os arquivos com extensão .gcda sejam removidos, a contagem do número de vezes que cada linha do código fonte foi executado será somada aos resultados das execuções anteriores. Embora você possa não desejar resultados acumulados, este fato pode ser útil de diversas formas, como por exemplo, caso deseje acumular dados de uma grande quantidade de execuções do programa para fornecer informações mais apuradas.

Algumas linhas do arquivo gcovTest.c.gcov contém informações sobre a linha de código zero ( 0 ). Estas linhas referem-se a algumas características, como por exemplo, o nome código fonte, o arquivo que contém informações sobre os grafos, a quantidade de execuções do programa, etc.

Para obter resultados mais detalhados e interessantes utilize o Gcov com a opção "-b". O resultado produzido será semelhante à imagem abaixo.

        -:    0:Source:gcovTest.c 
        -:    0:Graph:gcovTest.gcno 
        -:    0:Data:gcovTest.gcda 
        -:    0:Runs:1 
        -:    0:Programs:1 
        -:    1:#include <stdio.h> 
        -:    2: 
function main called 1 returned 100% blocks executed 86% 
        1:    3:int main (void) 
        -:    4:{ 
        -:    5: int i, total; 
        1:    6: total = 0; 
       21:    7: for (i = 0; i < 20; i++){ 
branch  0 taken 95% 
branch  1 taken 5% (fallthrough) 
       20:    8:   total += i; 
       20:    9:    if (total != 50){ 
branch  0 taken 100% (fallthrough) 
branch  1 taken 0% 
       20:   10:       printf ("Falha\n"); 
call    0 returned 100% 
        -:   11:     }else{ 
    #####:   12:       printf ("Sucesso\n"); 
call    0 never executed 
        -:   13:      } 
        -:   14:   } 
        1:   15:  return 0; 
        -:   16:}

Note que para cada função é impressa uma linha mostrando quantas vezes a função é chamada, quantas vezes ela retorna e qual a porcentagem com que os blocos das funções foram executadas.

Para cada bloco é impressa uma linha após a última linha do bloco descrevendo a chamada que finaliza o bloco. Podem ocorrer casos com múltiplas ramificações para uma única linha de código caso hajam múltiplos blocos que terminem sua execução naquela linha.

Para uma ramificação, se ela foi executada ao menos uma vez, então será impressa a porcentagem indicando o número de vezes que esta ramificação foi chamada dividido pelo numero de vezes que ela foi executada. Caso contrário uma mensagem "never executed" será mostrada.


Conclusão

Com o Gcov é possível fazer cobertura de código fonte de um programa. O Gcov gera uma contagem do número de vezes que cada linha de código foi executada em um programa.

Estas estatísticas são muito importante pois ajudam a localizar partes do programa que não foram executadas.


REFERÊNCIAS

[ 1 ] Miller, Joan C.; Maloney, Clifford J.. Systematic mistake analysis of digital computer programs.

[ 2 ] GNU GCC. Retirado em Junho de 2012.
http://gcc.gnu.org/

Comentários

developerWorks: Conecte-se

Los campos obligatorios están marcados con un asterisco (*).


Precisa de um ID IBM?
Esqueceu seu ID IBM?


Esqueceu sua senha?
Alterar sua senha

Ao clicar em Enviar, você concorda com os termos e condições do developerWorks.

 


A primeira vez que você entrar no developerWorks, um perfil é criado para você. Informações no seu perfil (seu nome, país / região, e nome da empresa) é apresentado ao público e vai acompanhar qualquer conteúdo que você postar, a menos que você opte por esconder o nome da empresa. Você pode atualizar sua conta IBM a qualquer momento.

Todas as informações enviadas são seguras.

Elija su nombre para mostrar



Ao se conectar ao developerWorks pela primeira vez, é criado um perfil para você e é necessário selecionar um nome de exibição. O nome de exibição acompanhará o conteúdo que você postar no developerWorks.

Escolha um nome de exibição de 3 - 31 caracteres. Seu nome de exibição deve ser exclusivo na comunidade do developerWorks e não deve ser o seu endereço de email por motivo de privacidade.

Los campos obligatorios están marcados con un asterisco (*).

(Escolha um nome de exibição de 3 - 31 caracteres.)

Ao clicar em Enviar, você concorda com os termos e condições do developerWorks.

 


Todas as informações enviadas são seguras.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=80
Zone=Linux
ArticleID=839527
ArticleTitle=Introdução ao GCOV
publish-date=10102012