Page suivante - Page précédente - Table des matières

5. Déboguer et optimiser

5.1 Etude préventive du code (lint)

Il n'existe pas de lint qui soit réellement utilisable, tout simplement parce que la grande majorité des développeurs sont satisfaits des messages d'avertissement de gcc. Il est probable que l'option la plus utile est l'option -Wall --- qui a pour effet d'afficher tous les avertissements possibles.

Il existe une version du domaine public du programme lint que vous pouvez trouver à l'adresse suivante : ftp://larch.lcs.mit.edu/pub/Larch/lclint. Je ne sais pas ce qu'elle vaut.

5.2 Déboguer

Comment rendre débogable un programme ?

Vous devez compiler et effectuer l'édition de liens avec l'option -g, et sans l'option -fomit-frame-pointer. En fait, vous ne devez compiler que les modules que vous avez besoin de déboguer.

Si vous possédez un système a.out, les bibliothèques dynamiques sont compilées avec l'option -fomit-frame-pointer, que gcc ne peut pas gérer. Lorsque vous compilez avec l'option -g, alors par défaut vous effectuez une édition de liens statique, ce qui permet de résoudre le problème.

Si l'éditeur de liens échoue avec un message disant qu'il n'arrive pas à trouver la bibliothèque libg.a, c'est que vous ne possédez pas la bibliothèque /usr/lib/libg.a, qui est la bibliothèque C standard permettant le débogage. Cette bibliothèque est fournie dans le paquetage des binaires de la libc., ou (dans les nouvelles versions) vous aurez besoin de récupérer le source et de le compiler vous-même. Vous n'avez pas réellement besoin de cela en fait, vous pouvez faire un lien logique vers /usr/lib/libc.a

Comment réduire la taille des exécutables ?

Bon nombre de produits GNU sont fournis pour compiler avec l'option -g, ce qui génère des exécutables d'une taille très importante (et souvent l'édition de liens s'effectue d'une manière statique). Ce n'est pas une idée lumineuse...

Si le programme possède le script configure généré par autoconf, vous pouvez modifier les options de débogage en effectuant un ./configure CFLAGS= ou ./configure CFLAGS=-O2. Sinon, vous pouvez aller modifier le Makefile. Bien sûr, si vous utilisez le format ELF, l'édition de liens sera effectuée de manière dynamique même avec l'option -g. Dans ce cas, vous pouvez effectuer un strip sur l'exécutable.

Programmes disponibles

Beaucoup de gens utilisent gdb, que vous pouvez récupérer sur le site prep.ai.mit.edu, sous une forme binaire sur tsx-11 ou sur sunsite. xxgdb est une surcouche X de gdb (c.a.d. que vous avez besoin de gdb pour utiliser xxgdb). Les sources peuvent être récupérés sur ftp://ftp.x.org/contrib/xxgdb-1.08.tar.gz

Il existe également le débogueur UPS qui a été porté par Rick Sladkey. Il fonctionne sous X également, mais à la différence d'xxgdb, ce n'est qu'une surcouche X pour un débogueur en mode en texte. Il possède certaines caractéristiques très intéressantes et si vous utilisez beaucoup ce genre d'outils, vous l'essayerez sûrement. Les patches ainsi que des versions précompilées pour Linux peuvent être trouvées sur ftp://sunsite.unc.edu/pub/Linux/devel/debuggers/, et les sources peuvent être récupérés sur ftp://ftp.x.org/contrib/ups-2.45.2.tar.Z.

Un autre outil que vous pouvez trouver utile pour déboguer est « strace » , qui affiche les appels systèmes que le processus lance. Il possède d'autres caractéristiques telles que donner les chemins d'accès où ont été compilés les binaires, donner les temps passés dans chacun des appels systèmes, et il vous permet également de connaître les résultats des appels. La dernière version de strace (actuellement la version 3.0.8) peut être trouvée sur ftp://ftp.std.com/pub/jrs/.

Programmes en tâche de fond (démon)

Les démons lancent typiquement un fork() dès leur lancement et terminent donc le père. Cela fait une session de déboguage très courte.

La manière la plus simple de résoudre ce problème est de poser un point d'arrêt sur fork, et lorsque le programme s'arrête, forcer le retour à 0.

(gdb) list
1       #include <stdio.h>
2
3       main()
4       {
5         if(fork()==0) printf("child\n");
6         else printf("parent\n");
7       }
(gdb) break fork
Breakpoint 1 at 0x80003b8
(gdb) run
Starting program: /home/dan/src/hello/./fork
Breakpoint 1 at 0x400177c4
Breakpoint 1, 0x400177c4 in fork ()
(gdb) return 0
Make selected stack frame return now? (y or n) y
#0  0x80004a8 in main ()
 at fork.c:5
5         if(fork()==0) printf("child\n");
(gdb) next
Single stepping until exit from function fork,
which has no line number information.
child
7       }

Fichiers core

Lorsque Linux se lance, il n'est généralement pas configuré pour produire des fichiers core. Si vous les voulez vous devez utiliser votre shell pour ça en faisant sous csh (ou tcsh) :

% limit core unlimited
avec sh, bash, zsh, pdksh, utilisez
$ ulimit -c unlimited

Si vous voulez pousser le vice à nommer votre fichier core (par exemple si vous utilisez un débogueur bogué... ce qui est un comble) vous pouvez simplement modifier le noyau. Editez les fichiers fs/binfmt_aout.c et fs/binfmt_elf.c (dans les nouveaux noyaux, vous devrez chercher ailleurs) :

 memcpy(corefile,"core.",5);
#if 0
 memcpy(corefile+5,current->comm,sizeof(current->comm));
#else
 corefile[4] = '\0';
#endif

et changez les 0 par des 1.

5.3 Caractéristiques du programme

Il est possible d'examiner un peu le programme pour savoir quels sont les appels de fonctions qui sont effectués le plus souvent ou bien qui prennent du temps. C'est une bonne manière d'optimiser le code en déterminant là où l'on passe le plus de temps. Vous devez compiler tous les objets avec l'option -p, et pour mettre en forme la sortie écran, vous aurez besoin du programme gprof (situé dans les binutils). Consultez les pages de manuel gprof pour plus de détails.


Page suivante - Page précédente - Table des matières