Les spécifications des langages, notamment celles du C et du C++, sont souvent rédigées de manière peu rigoureuse. Un outil appelé lint peut vous aider à trouver des constructions dangereuses et non portables dans votre code avant que votre compilateur ne les transforme en bogues d’exécution.
Toute personne ayant écrit un programme a dû déboguer du code. Dans de nombreux cas, après avoir fixé le code pendant des heures, nous réalisons finalement que nous avons fait quelque chose de stupide comme lire une variable non initialisée, ou indexer au-delà de la fin d’un tableau. Avec l’expérience, l’incidence de ces bugs » doh ! » diminue ; mais ils peuvent toujours être extrêmement frustrants et coûteux.
Ce dont nous avons besoin dans ces moments-là, c’est d’un expert infiniment patient et anal-rétentif pour inspecter chaque pouce de notre code. Cet expert doit être plus minutieux que n’importe quel compilateur, et doit rapporter de manière totalement dépassionnée tout ce qui est potentiellement mauvais dans notre code. Un outil de programmation appelé lint est ce qui se rapproche le plus de cet idéal. Si vous ne savez pas ce qu’est lint, ou si vous ne l’utilisez pas, je vous suggère de lire la suite.
Lint est un outil similaire à un compilateur dans la mesure où il analyse les fichiers sources C/C++. Il vérifie l’exactitude syntaxique de ces fichiers. Pour lint un fichier appelé foo.c, il suffit typiquement de taper :
lint foo.c
à la ligne de commande. Mais naturellement, il existe aussi de nombreux commutateurs de ligne de commande optionnels.
Fonctionnalités standard
Là où un compilateur se préoccupe principalement de la génération de code, lint est entièrement consacré à la vérification de votre code pour une myriade de défauts possibles. Le mot clé ici est « possible ». Ce n’est pas parce que lint signale une section de votre code pour examen que cela signifie nécessairement qu’un problème se produira lorsque vous compilerez ce code avec votre compilateur particulier.
Lint est conçu pour être agnostique vis-à-vis des compilateurs et a, en fait, fréquemment pour mission d’attirer votre attention sur des parties du code qui pourraient entraîner un comportement différent selon le compilateur spécifique utilisé.
La liste spécifique des problèmes que lint vérifie varie selon l’implémentation et la version de l’outil. Cependant, la plupart des saveurs de lint vérifieront au moins les éléments suivants :
- Utilisation possible de variables non initialisées
- Indexation possible au-delà des limites du tableau
- Dé-référencement de pointeurs nuls
- Attributions suspectes (telles que if (a = b))
- Désaccords dans les types de variables (tels que foo déclaré comme un double dans un fichier et utilisé comme un long dans un autre)
- Combinaisons de types de données potentiellement dangereuses
- Variables inutilisées
- Code inaccessible
- Fichiers d’en-tête inclus plusieurs fois et/ou inutilement
- Constructions non-portable constructs
Lint vérifie tellement de choses, en fait, qu’il est habituel que l’outil produise autant d’erreurs et d’avertissements qu’il y a de lignes de code dans le fichier source qui est entré. Cela rebute beaucoup d’utilisateurs potentiels, car leur attitude tend à être « cet outil est si pointilleux qu’il en est ridicule ». Cependant, travailler sur chaque avertissement et le corriger peut être un exercice enrichissant. À titre d’exemple, considérez ce code apparemment inoffensif :
main(void){int i;for(i = 0; i
Quel sera le dernier nombre imprimé lorsque vous exécuterez ce programme ? Si vous avez répondu » 100 « , vous avez tort. Ce programme est parfaitement valide, et compilera sans avertissement sur la plupart des compilateurs. Cependant, lint se plaindra de quelque chose. Si vous ne pouvez pas voir le problème par inspection, je vous suggère de télécharger le code sur www.embedded.com/code.htm et de l’exécuter avec votre débogueur préféré. Note, et un gros conseil ici : ne tapez pas simplement ce programme dans votre éditeur. Observez le temps qu’il vous faut pour trouver ce problème – et demandez-vous ensuite si patauger dans les avertissements de lint n’est pas si mal.
Sortir la lint
Malgré l’exemple légèrement inventé ci-dessus, quelle sorte de bénéfice dans le monde réel pouvez-vous attendre de la prise en compte de tous les avertissements produits par lint ? Mes expériences sur un projet typique impliquant un petit microcontrôleur (taille totale du code inférieure à 32 Ko) comprenaient les éléments suivants :
- Lint a trouvé deux ou trois bogues purs et simples – avant même que je ne commence à tester le code.
- J’ai appris quelque chose sur le langage C chaque fois que je l’ai exécuté.
- Mon code final était plus propre parce que lint m’a informé des variables inutilisées, des macros et des inclusions de fichiers d’en-tête qui pouvaient être supprimées en toute sécurité.
- J’étais mieux informé des problèmes potentiels de portabilité.
Compte tenu de ce qui précède, vous ne serez probablement pas surpris d’apprendre que les organisations qui sont vraiment sérieuses au sujet de la qualité du code insistent souvent non seulement pour que tout le code compile sans avertissements (ce qui est relativement trivial à réaliser), mais aussi pour qu’il soit » lint free » – c’est-à-dire qu’il ne génère aucun avertissement avec lint. Il s’agit là d’un critère beaucoup plus difficile à atteindre.
Figure 1 : Comment lint s’intègre dans le processus de développement
Il vaut la peine de regarder où lint s’intègre dans le processus de développement. Mon flux de conception général est illustré à la figure 1. Une fois que j’ai du code qui se compile, je le lint. Si le code passe bien la lint, il est très peu probable que je sois embarrassé lors de la revue de code. Pendant la phase de débogage, il est normal que des modifications soient apportées au code. Cependant, une fois que le code est débogué, et avant qu’il ne passe au test de la version, je repasse normalement le code en revue. Pourquoi ? Je suis toujours étonné par le nombre de constructions de codage bâclées qui se produisent lorsque le code est débogué. Lint est un outil formidable pour identifier ce morceau de code miteux qui a été mis là pour aider à déboguer quelque chose et qui a été promptement oublié.
Sources de lint
Lint est un outil standard sur la plupart des systèmes Unix. Dans le royaume des PC, vous devez souvent sortir et l’acheter, ou trouver une version gratuite ou shareware. Si vous achetez lint, soyez assuré que ce sera probablement le meilleur argent que vous ayez jamais dépensé dans votre carrière embarquée. La plupart des variantes de lint sont relativement peu coûteuses (moins de 1 000 $) et valent chaque centime.
Au passage, vous vous demandez peut-être si lint gère bien toutes ces méchantes petites extensions de compilateur qui sont si courantes dans le développement embarqué. C’est un domaine où les programmes commerciaux surpassent les offres standard. En particulier, certaines versions de lint permettent une personnalisation considérable des règles de lint, de sorte que toutes ces extensions sont correctement gérées. Dans certains cas, les définitions du compilateur sont même fournies par le vendeur de lint. Dans d’autres, vous pouvez les obtenir auprès du vendeur du compilateur.
Si vous n’avez pas accès à lint, mais que vous utilisez les outils GNU (sur Unix ou un PC), utilisez simplement le drapeau -Wall de gcc pour obtenir environ 80 % des mêmes fonctionnalités.
Alors, pour tous les néophytes, procurez-vous une copie de lint, et utilisez-la. Si rien d’autre, votre patron sera impressionné par la maturité de votre code. Pour tous les hackers expérimentés qui n’utilisent pas lint, faites attention ! Les nouveaux qui l’utilisent pourraient bien vous en remontrer.
Nigel Jones est consultant dans le Maryland. Quand il n’est pas sous l’eau, on peut le trouver en train de trimer sur une grande variété de projets embarqués. Il apprécie d’avoir des nouvelles des lecteurs et peut être joint à .
.