Domanda

Io corro gcov sopra po 'di codice C con un'istruzione switch. Ho scritto casi di test per coprire ogni possibile percorso attraverso quel istruzione switch, ma segnala ancora una filiale nella dichiarazione switch come non godute e inferiore al 100% sulla "assunto almeno una volta" stat.

Ecco alcuni esempi di codice per dimostrare:

#include "stdio.h"

void foo(int i)
{
    switch(i)
    {
        case 1:printf("a\n");break;
        case 2:printf("b\n");break;
        case 3:printf("c\n");break;
        default: printf("other\n");
    }
}

int main()
{
    int i;
    for(i=0;i<4;++i)
        foo(i);
    return 0;
}

ho costruito con "gcc temp.c -fprofile-arcs -ftest-coverage", ran "a", poi ha fatto "gcov -b -c temp.c". L'output indica otto rami sull'interruttore ed uno (ramo 6) non presa.

Cosa sono tutti quei rami e come faccio ad avere una copertura del 100%?

È stato utile?

Soluzione 4

Sto usando MinGW su Windows (che non è l'ultimo gcc) e sembra che questo può essere risolto nelle nuove versioni di gcc.

Altri suggerimenti

Oho! spettacoli discarica di assemblaggio del BDE che tale versione di GCC è la compilazione di questa dichiarazione switch come qualche approssimazione di un albero binario, a partire dalla metà del set. Quindi controlla se i è uguale a 2, quindi controlla se è maggiore o minore di 2, e poi per ogni lato controlla se è uguale a 1 o 3 rispettivamente, e se no, poi si va a default.

Ciò significa che ci sono due percorsi di codice differenti per poter raggiungere il risultato di default - uno per i numeri superiori a 2 che non sono 3, e uno per i numeri inferiore a 2 che non sono 1

.

Sembra che si otterrà a copertura del 100% se si modifica che i<4 nel vostro ciclo per i<=4, in modo da verificare il percorso su ogni lato.

(E, sì, questo è qualcosa che è molto probabile che sono cambiato da GCC 3.x a GCC 4.x. io non direi che è "fisso", in quanto non è "sbagliato" esattamente oltre a fare i risultati gcov confondendo. E 'solo che su un processore moderno con branch prediction, è probabilmente lenta, così come eccessivamente complicato.)

ottengo lo stesso risultato utilizzando gcc / gcov 3.4.6.

Per un'istruzione switch, si dovrebbe di norma generare due rami per ogni affermazione caso. Uno è se il caso è vera e deve essere eseguito, e l'altro è un ramo "falltrough" che va avanti per il prossimo caso.

Nella tua situazione, sembra che gcc sta facendo un ramo "falltrough" per l'ultimo caso, che non ha senso dal momento che non c'è nulla da cadere in.

Ecco un estratto dal codice assembly generato da gcc (ho cambiato alcune delle etichette per facilitarne la lettura):

    cmpl    $2, -4(%ebp)
    je  CASE2
    cmpl    $2, -4(%ebp)
    jg  L7
    cmpl    $1, -4(%ebp)
    je  CASE1
    addl    $1, LPBX1+16
    adcl    $0, LPBX1+20
    jmp DEFAULT
L7:
    cmpl    $3, -4(%ebp)
    je  CASE3
    addl    $1, LPBX1+32
    adcl    $0, LPBX1+36
    jmp DEFAULT

Ammetto che io non so molto di X 86 di assemblaggio, e non capisco l'uso del marchio L7, ma che potrebbe avere qualcosa a che fare con il ramo più. Forse qualcuno con più conoscenza di gcc può spiegare cosa sta succedendo qui.

E 'suona come potrebbe essere un problema con la versione precedente di gcc / gcov, l'aggiornamento a una versione più recente gcc / gcov potrebbe risolvere il problema, soprattutto in considerazione l'altro post in cui i risultati sembrano corrette.

Sei sicuro si sta eseguendo a.out? Ecco i miei risultati (GCC 4.4.1):

File 't.c'
Lines executed:100.00% of 11
Branches executed:100.00% of 6
Taken at least once:100.00% of 6
Calls executed:100.00% of 5
t.c:creating 't.c.gcov'
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top