2017-09-23 14 views
4

내 매뉴얼 페이지libgcov 포크와 간부 후크 <code>--coverage</code> 옵션에 대한 GCC의 주장

또한 "포크"전화가 감지되고 올바르게 처리 (이중 계산이 일어나지 않을 것입니다).

는 그리고 내 /usr/lib/gcc/x86_64-linux-gnu/5.4.0/libgcov.a 심볼 __gcov_fork, __gcov_execl 및 기타 __gcov_exec* 변종을 포함 확인할 수 있습니다. 온라인에서 이러한 함수의 정의를 살펴보면 데이터를 복제하거나 잃어 버리지 않도록 범위 출력을 덤프하고 지우는 것처럼 보입니다.

그러나이하지 않는 것 나를 위해 일하게 : 그것은 "아이 1"프로세스처럼 나에게 보이는

gcov_test$ rm *.gcno *.gcda 
gcov_test$ cat gcov_test.c 
#include <stdlib.h> 
#include <stdio.h> 
#include <unistd.h> 
#include <sys/types.h> 
#include <sys/wait.h> 

int main(void) { 
    puts("Before loop"); 
    for (int i=0; i<5; ++i) 
     printf("i=%d\n", i); 
    puts("After loop"); 
    pid_t child1 = fork(); 
    if (child1<0) { 
     perror("fork 1"); 
     exit(1); 
    } else if (child1==0) { 
     printf("In child 1: %d\n", (int)getpid()); 
     execl("/bin/true", "/bin/true", (char*)NULL); 
     perror("execl"); 
     exit(1); 
    } 
    printf("Parent spawned child 1: %d\n", (int)child1); 
    pid_t child2 = fork(); 
    if (child2<0) 
    { 
     perror("fork 2"); 
     exit(1); 
    } else if (child2==0) { 
     printf("In child 2: %d\n", (int)getpid()); 
    } else { 
     printf("Parent spawned child 2: %d\n", (int)child2); 
     if (waitpid(child1, NULL, 0)<0) 
      perror("waitpid 1"); 
     if (waitpid(child2, NULL, 0)<0) 
      perror("waitpid 2"); 
     puts("Parent done"); 
    } 
    return 0; 
} 

gcov_test$ gcc --version 
gcc (Ubuntu 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609 
Copyright (C) 2015 Free Software Foundation, Inc. 
This is free software; see the source for copying conditions. There is NO 
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 

gcov_test$ gcc -c -std=c11 -Wall --coverage gcov_test.c 
gcov_test$ gcc --coverage gcov_test.o -o gcov_test 
gcov_test$ ./gcov_test 
Before loop 
i=0 
i=1 
i=2 
i=3 
i=4 
After loop 
Parent spawned child 1: 31569 
Parent spawned child 2: 31570 
In child 2: 31570 
In child 1: 31569 
Parent done 
gcov_test$ gcov gcov_test.c 
File 'gcov_test.c' 
Lines executed:64.29% of 28 
Creating 'gcov_test.c.gcov' 

gcov_test$ cat gcov_test.c.gcov 
     -: 0:Source:gcov_test.c 
     -: 0:Graph:gcov_test.gcno 
     -: 0:Data:gcov_test.gcda 
     -: 0:Runs:2 
     -: 0:Programs:1 
     -: 1:#include <stdlib.h> 
     -: 2:#include <stdio.h> 
     -: 3:#include <unistd.h> 
     -: 4:#include <sys/types.h> 
     -: 5:#include <sys/wait.h> 
     -: 6: 
     2: 7:int main(void) { 
     2: 8: puts("Before loop"); 
     12: 9: for (int i=0; i<5; ++i) 
     10: 10:  printf("i=%d\n", i); 
     2: 11: puts("After loop"); 
     2: 12: pid_t child1 = fork(); 
     2: 13: if (child1<0) { 
    #####: 14:  perror("fork 1"); 
    #####: 15:  exit(1); 
     2: 16: } else if (child1==0) { 
    #####: 17:  printf("In child 1: %d\n", (int)getpid()); 
    #####: 18:  execl("/bin/true", "/bin/true", (char*)NULL); 
    #####: 19:  perror("execl"); 
    #####: 20:  exit(1); 
     -: 21: } 
     2: 22: printf("Parent spawned child 1: %d\n", (int)child1); 
     2: 23: pid_t child2 = fork(); 
     2: 24: if (child2<0) 
     -: 25: { 
    #####: 26:  perror("fork 2"); 
    #####: 27:  exit(1); 
     2: 28: } else if (child2==0) { 
     1: 29:  printf("In child 2: %d\n", (int)getpid()); 
     -: 30: } else { 
     1: 31:  printf("Parent spawned child 2: %d\n", (int)child2); 
     1: 32:  if (waitpid(child1, NULL, 0)<0) 
    #####: 33:   perror("waitpid 1"); 
     1: 34:  if (waitpid(child2, NULL, 0)<0) 
    #####: 35:   perror("waitpid 2"); 
     1: 36:  puts("Parent done"); 
     -: 37: } 
     2: 38: return 0; 
     -: 39:} 
     -: 40: 
gcov_test$ 

결코 특히 "In child 1" 라인이 실행 된 이후, 파일에의 적용 결과를 썼다 없지만, 포함 된대로 표시되지 않습니다. 그리고 두 번째 전에 모든 라인은 fork 이중 커버리지를보고하는 것으로 보입니다. 따라서 man 페이지가 주장 된대로 fork을 호출 할 때 커버리지 결과가 리셋되지 않았습니다.

libgcov 후크를 사용하려면 어떻게해야합니까? 나는 실제 syscalls를 실제 훅 이름으로 대체하기로되어 있지 않다. 단지 커버리지 모드에서 컴파일 할 때이다.

답변

2

해결책 : c11gnu11으로 대체하십시오.

-std=c11은 순수한 C11 (GNU 확장 없음)을 의미합니다. -std=gnu11은 또한 GNU 확장을 가능하게합니다. -std=--coverage 사이의 연결을 설명 할 수 없으며 (일반적으로 -std=은 내장 함수 사용에 영향을 미치고 __gcov_fork은 그 중 하나임) 단순히 표준을 gnu11으로 변경하면 문제가 해결되는 것 같습니다. 29의 실행 횟수는 1입니다. (GCC 5.4.0과 최신 트렁크 개정판에서 모두 시도했습니다).

P. 버그 리포트를 제출하는 것이 좋습니다. 이 동작이 의도 된 것이라 할지라도 컴파일러는 잠재적 인 문제에 대해 최소한 경고해야합니다.

+0

수정 :'__gcov_fork'는 기본 제공 함수가 아닙니다. 'exec *'와'fork'가 있습니다. –