2017-09-23 5 views
4

Mein Mann Seite für gcc Behauptungen über die --coverage Option:libgcov fork und exec Haken

Auch „fork“ Anrufe erkannt und richtig behandelt (Doppelzählung wird nicht passieren).

Und ich merke, meine /usr/lib/gcc/x86_64-linux-gnu/5.4.0/libgcov.a Symbole enthält __gcov_fork, __gcov_execl und andere __gcov_exec* Varianten. Wenn Sie online nach den Definitionen dieser Funktionen suchen, sieht es so aus, als würden sie die Coverage-Ausgabe ausgeben und löschen, um zu vermeiden, dass die Daten dupliziert oder verloren gehen.

Aber dies scheint nicht für mich arbeiten zu werden:

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$ 

Es mir nie da Datei, insbesondere die Abdeckung wie das „Kind 1“ Prozess sieht Ergebnisse schrieb die "In child 1" Linie ausgeführt, aber wird nicht als abgedeckt angezeigt. Und alle Zeilen vor der Sekunde fork scheinen doppelte Abdeckung zu melden, also scheint es, dass die Abdeckungsergebnisse bei Aufruf fork nicht zurückgesetzt wurden, wie die man-Seite behauptete.

Gibt es noch etwas, was ich tun muss, um diese libgcov-Hooks zu aktivieren? Ich sollte eigentlich nicht die Systemaufrufe mit den tatsächlichen Hook-Namen ersetzen, nur wenn ich im Coverage-Modus kompiliere, oder?

Antwort

2

Lösung: ersetzen c11 durch gnu11.

-std=c11 bedeutet reines C11 (ohne GNU-Erweiterungen). -std=gnu11 aktiviert auch GNU-Erweiterungen. Ich kann die Verbindung zwischen -std= und --coverage nicht erklären (vermutlich -std= betrifft eingebaute Funktionsverwendung im Allgemeinen, und __gcov_fork ist einer von ihnen), aber einfach den Standard zu ändern gnu11 scheint das Problem zu lösen, dh, beide Linie 17 und 29 haben nun eine Ausführungszahl von 1. (Ich habe es sowohl mit GCC 5.4.0 als auch mit einer kürzlichen Stammrevision versucht).

P.S. Ich schlage vor, dass Sie einen Fehlerbericht einreichen. Auch wenn dieses Verhalten beabsichtigt ist, sollte uns der Compiler zumindest vor möglichen Problemen warnen.

+0

Fix: '__gcov_fork' ist keine eingebaute Funktion. 'exec *' und 'fork' sind. –