Date de première publication : 2018/09/24
Dans ce premier TP de C, nous allons introduire les outils dont nous aurons besoin pour travailler en C cette année.
- les outils de débogage et de profilage
- la bibliothèque de tests unitaires
Nous allons tester et corriger le programme suivant :
#include
void essai(int j)
{
int i;
while(i<10)
{
printf("%d ", i+j );
++i;
}
}
int main()
{
int j;
for(j=0; j< 10; ++j)
{
essai(j);
printf("\n");
}
return 0;
}
Mise en place (git)
Il est possible de récupérer le programme de différentes manières :
- Le taper (et ajouter les bons entêtes)
- le copier-coller
- Utiliser un gestionnaire de version comme git
Il faut tout d'abord configurer son compte pour utiliser un tel utilitaire. Tapez les commandes suivantes :
git config --global user.name "un_nom"
git config --global user.email "un_mail"
If faut ensuite récupérer le code, cela va créer le répertoire C1A avec le bon fichier dedans :
git clone https://gitlab.com/kiux/C1A.git
Vous pouvez trouver ce qui ne va pas sans les outils mais vous allez les utiliser quand même.
- Compilez le programme et exécutez-le.
- Il est tout à fait possible que le programme semble donner ce que l'on attend mais il faut tester ce que cela donne !
- Recompilez le programme en ajoutant l'option
-g
pour donner l'ordre au compilateur d'insérer des informations de déboguage dans l'exécutable.
En règle générale, c'est une excellente idée de compiler les programmes en développement avec cette option -g
. On enlève cette option lorsque le programme est compilé pour le distribuer à l'utilisateur final.
valgrind
Le premier outil que nous allons utiliser est valgrind. Cet outil simule l'exécution de notre programme et va analyser tout un tas d'informations. Nous allons avons avoir, entre autres, toutes les anomalies mémoire :
valgrind ./executable
Le résultat est le suivant :
==19248== Conditional jump or move depends on uninitialised value(s)
==19248== at 0x400574: essai (ddd01.c:17)
==19248== by 0x400593: main (ddd01.c:30)
==19248== Use --track-origins=yes to see where uninitialised values come from
==19248== ERROR SUMMARY: 800 errors from 7 contexts (suppressed: 0 from 0)
L'exécution suivante peut donner encore plus d'informations :
valgrind --track-origins=yes ./executable
Vous avez le numéro de ligne, c'est facile maintenant de corriger ! Mais ne le faites pas encore...
ddd
Nous allons maintenant utiliser le débogeur gdb
au travers de sa surcouche graphique ddd
.
ddd nom_executable_a_tester &
L'interface graphique de débogueur se lance alors et ressemble à ça :
Posez un point d'arrêt sur la première instruction de la fonction essai()
en double cliquant (Un STOP apparait). Puis
exécutez le programme ligne par ligne jusqu'à trouver l'erreur.
Le curseur flèche verte indique la prochaine instruction à être exécutée.
Si vous avez de la "chance", vous verrez tout de suite ce qui se passe et vous pourrez alors corriger !
ddd n'aime pas certains encodages de fichier ou les accents dans les commentaires. Les symptômes : l'affichage graphique des variables qui ne marche pas ou bien un affichage incomplet du code.
Dans le support de cours en ligne C3, vous trouverez les commandes pour utiliser le débogueur en version texte.
Bibliothèque de tests
De nombreux TPs vont se faire en utilisant des "tests unitaires". Le principe est de tester régulièrement le code que l'on est en train d'écrire en le confrontant à ce que l'on veut obtenir. Le développement est réputé "terminé" lorsque tous les tests réussissent. (Bien entendu, dans un mode idéal, où les tests couvrent tous les cas possibles d'exécution et que d'autres types de tests ont été réussis)
Vous devez récupérer les fichiers de code pour cet exercice :
main.c
contient le point d'entrée du programme de test ainsi que les tests eux-mêmes.mon_code.h
contient les déclarations des fonctions à écriremon_code.c
contient l'implémentation des fonctions à écrire (c'est à compléter)teZZt.h
contient les déclarations de tout ce qui est nécessaire pour la bibliothèque de teststeZZt.c
contient l'implémentation de la bibliothèque de tests.
git clone https://gitlab.com/kiux/C1B.git
Pour compiler le tout, vous pouvez faire une commande gcc
générale mais vous pouvez aussi simplement lancer la commande :
make
Cela exécute des instructions de compilation (encore appelées règles) contenues dans le fichier Makefile
lui-aussi fourni.
Premiers tests
On vous demande de coder la fonction pgcd()
qui calcule le plus grand diviseur commun entre deux nombres entiers. Si vous complétez le code de la fonction dans le fichier mon_code.c
, les tests seront réussis (OK ou passed) et non plus en echec (KO ou failed) !
main.c: 9 | EXPECT : 12 == pgcd(36, 24) main.c: 10 | EXPECT : 3 == pgcd(96, 81) main.c: 11 | EXPECT : 1 == pgcd(17, 1) main.c: 17 | EXPECT : 12 == pgcd(24, 36) main.c: 18 | EXPECT : 3 == pgcd(81, 96) main.c: 19 | EXPECT : 1 == pgcd( 1, 17) --- teZZT REPORT --- 6 test(s) failed 0 test(s) passed
Au passage, le pgcd de deux nombres a
et b
vautb
si le reste de la division entière de a
par b
est nul sinon c'est le pgcd de b
et de ce reste (définition récursive).
Transformer en majuscules
Vous pouvez ensuite décommenter les tests suivants. Il s'agit de tester la fonction majuscules()
que vous avez écrite pendant les semaines bloquées (vous pouvez réutiliser ce que vous avez écrit naturellement).
On vérifie ce qu'il se passe quand la chaîne en paramètre est vide, quand elle ne contient que des majuscules, que des minuscules et quand elle contient également des caractères qui ne sont pas des lettres.
TEST(maj4) {
char s[255] = "aAbB2eDdD!";
majuscules(s);
CHECK( 0 == strcmp( s, "AABB2EDDD!") );
}
Vous pouvez ajouter des tests complémentaires si vous le désirez.