Ma page de manuel pour les demandes de gcc sur l'option --coverage
:fourche libgcov et crochets exec
sont détectées et traitées correctement également les appels « fourchette » (double comptage ne se produira pas).
Et je remarque que mon /usr/lib/gcc/x86_64-linux-gnu/5.4.0/libgcov.a contient des symboles __gcov_fork
, __gcov_execl
et autres __gcov_exec*
variantes. En regardant les définitions de ces fonctions en ligne, il semble qu'ils videraient et effaceraient la sortie de la couverture pour éviter la duplication ou la perte des données.
Mais cela ne semble pas fonctionner pour moi:
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$
Il semble à moi comme le processus « enfant 1 » n'a jamais écrit ses résultats de couverture à déposer, puisque notamment la ligne "In child 1"
exécutée mais n'est pas montré comme couvert. Et toutes les lignes avant la seconde fork
semblent signaler une couverture doublée, il semble donc que les résultats de la couverture n'ont pas été réinitialisés à l'appel fork
comme la page de manuel revendiquée.
Y at-il quelque chose d'autre que je dois faire pour activer ces crochets de libgcov? Je ne suis pas censé remplacer les syscalls avec les noms réels de crochet juste en compilant en mode de couverture, suis-je?
Correction: '__gcov_fork' n'est pas une fonction intégrée. 'exec *' et 'fork' sont. –