2010-05-11 6 views
12

일부 C 코드에 대해 switch 문을 사용하여 gcov를 실행하고 있습니다. 해당 switch 문을 통해 가능한 모든 경로를 다루기 위해 테스트 사례를 작성했지만 switch 문에서 분기가 "취해서"적어도 100 % 미만으로보고합니다.gcov 및 switch 문

여기에 몇 가지 예제 코드를 보여입니다 :

#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; 
} 

내가 "gcc temp.c -fprofile-arcs -ftest-coverage은"다음, "a"실행 "gcov -b -c temp.c을"한 빌드. 출력은 스위치에 8 개의 분기를 표시하고 하나는 분기하지 않음을 나타냅니다.

모든 지점은 무엇이며 어떻게 100 % 적용 범위를 얻을 수 있습니까?

+0

.gcda 파일의 내용이 도움이됩니까? – Cascabel

답변

0

Windows에서 mingw를 사용하고 있으며 이는 gcc가 아닌 것처럼 보입니다. 최신 버전의 gcc에서 정렬되었습니다.

1

a.out을 실행 하시겠습니까?

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' 
+0

그는''a.exe '를 실행했고 윈도우를 사용하고 있다고 제안했다. – nategoose

+0

나는 기본적으로 gcc와 유닉스를 연관 짓는다. 결과는 실수로 실행 파일의 다른 버전을 실행하는 것과 일관되게 보입니다. – ergosys

+0

예, Windows에서 MinGW를 사용하고 있습니다. gcc 3.4.5입니다. 이것은 gcc의 최신 버전에서 수정 된 내용 일 수 있습니까? – Matt

2

내가 GCC/gcov를 3.4.6을 사용하여 동일한 결과를 얻을 : 여기 내 결과 (GCC 4.4.1)입니다.

switch 문에 대해 일반적으로 각 case 문에 대해 두 개의 분기를 생성해야합니다. 하나는 사례가 사실이고 실행되어야하는 경우이고, 다른 하나는 다음 사례로 진행되는 "전환점"지점입니다.

상황에 따라 gcc가 마지막 사례에 대해 "폴 스루"분기를 만드는 것처럼 보입니다.이 경우에는 아무 것도 없어 질 것이므로 의미가 없습니다. 여기

는 GCC에 의해 생성 된 어셈블리 코드에서 발췌 한 것입니다 (I 가독성에 대한 라벨의 일부를 변경) :

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 

내가 86 어셈블리에 대해 잘 모르는 것을 인정하고, 내가하지 L7 레이블의 사용법을 이해하고 있지만 추가 분기와 관련이있을 수 있습니다. 어쩌면 gcc에 대해 더 많은 지식을 가진 사람이 여기에서 무슨 일이 일어나고 있는지 설명 할 수 있습니다.

gcc/gcov의 이전 버전에서 문제가있는 것처럼 들리지만 새로운 gcc/gcov로 업그레이드하면 문제가 해결 될 수 있습니다.

+0

나는 그것이 gcov가 fallthrough 분기를 만드는 것을 의심한다; gcc가 할 가능성이 높아 보인다. 최적화를 사용하면 어떻게됩니까? –

+0

'default'에 대한 fallthrough가있는 데는 아무런 문제가 없습니다. 결국'default'에 해당하는 코드 실행을 피하기 위해 아래에'case'가있을 수 있습니다. 무엇이 잘못되었는지는 스위치의 마지막 문구에 대한 fallthrough가있는 것입니다. 왜냐하면 넘어 질 내용이 없기 때문입니다. –

+0

@Brooks 최적화를 켜도 문제가 변경되지 않으며 -O3 이상을 사용하면 더 많은 분기를 추가하는 것처럼 보입니다. – WildCrustacean

4

오오! bde의 어셈블리 덤프는이 버전의 GCC가이 스위치 문을 집합의 중간에서 시작하여 이진 트리의 근사치로 컴파일하고 있음을 보여줍니다. 따라서 i이 2인지 확인한 다음 2보다 크거나 작 으면 검사하고 각면에 대해 각각 1 또는 3인지 검사하고 그렇지 않은 경우 기본값으로 이동합니다.

두 개의 서로 다른 코드는 기본 결과를 얻기위한 경로가 의미

-3이없는 2 이상의 숫자 하나, 그리고 1

없는 2보다 낮은 숫자 하나

루프의 i<4i<=4으로 변경하면 각면의 경로를 테스트 할 수 있으므로 100 % 적용 범위를 초과하는 것처럼 보입니다.

(그렇습니다. GCC 3.x에서 GCC 4.x로 변경되었을 가능성이 매우 높습니다. gcov를 만드는 것 이외에 "잘못"하지 않았으므로 "고정"이라고 말하지 않습니다. 결과가 혼란 스럽습니다. 분기 예측을 사용하는 최신 프로세서의 경우에는 속도가 느리고 복잡하게 진행될 수 있습니다.)

관련 문제