{"id":20,"date":"2020-12-13T23:22:44","date_gmt":"2020-12-13T22:22:44","guid":{"rendered":"http:\/\/optimum-software.fr\/?page_id=20"},"modified":"2020-12-13T23:24:24","modified_gmt":"2020-12-13T22:24:24","slug":"20-2","status":"publish","type":"page","link":"https:\/\/optimum-software.fr\/?page_id=20","title":{"rendered":"Mise en oeuvre progressive des warnings de compilation en C\/C++"},"content":{"rendered":"\n<p>Ces derni\u00e8res ann\u00e9es, les compilateurs ont \u00e9norm\u00e9ment progress\u00e9 sur diff\u00e9rents aspects : optimisation (g\u00e9n\u00e9ration de code, LTO, \u2026), instrumentation (sanitizers), debug, vectorisation, \u2026 mais \u00e9galement concernant un sujet plus imm\u00e9diat et visible au quotidien : les warnings, que \u00e7a soit dans la d\u00e9tection des probl\u00e8mes ou la mani\u00e8re dont ils sont libell\u00e9s (pr\u00e9cision, suggestion, rappel du nom du warning concern\u00e9, \u2026). On peut sans doute saluer la comp\u00e9tition entre gcc (le r\u00e9f\u00e9rent historique) et clang (du projet LLVM) qui a d\u00e9pass\u00e9 le stade d\u2019outsider. Ce sont les deux compilateurs que nous consid\u00e9rerons (en focalisant sur les langages C et C++).<\/p>\n\n\n\n<p>Les options de warnings ne font souvent pas l\u2019objet d\u2019une attention particuli\u00e8re et se trouvent sous-utilis\u00e9es (par facilit\u00e9, m\u00e9connaissance, \u2026). Pourtant elles permettent d\u2019aller tr\u00e8s loin dans la recherche de faiblesses dans le code et au plus t\u00f4t (\u00e0 la compilation du code), l\u00e0 o\u00f9 les corrections co\u00fbtent peu ch\u00e8res. Le but de cet article est de prendre cette direction, de vous proposer un renforcement progressif des warnings en d\u00e9finissant plusieurs niveaux. L\u2019id\u00e9e est de se mettre dans la d\u00e9marche de choisir d\u00e9lib\u00e9r\u00e9ment un niveau adapt\u00e9 \u00e0 la situation du moment, en faisant d\u00e9couvrir les options qui existent.<\/p>\n\n\n\n<p>Comme pour d\u2019autres sujets concernant le d\u00e9veloppement logiciel, que ce soit la gestion de projet ou la strat\u00e9gie de test par exemple, il est imp\u00e9ratif de faire des choix. Le risque est moindre que de ne faire aucun choix. Mais nous allons le voir, comme bien souvent, il ne faut pas \u00eatre effray\u00e9 et s\u2019imaginer une tonne de process ou de questions pi\u00e8ges. On se tiendra loin des r\u00e8gles rigides et arbitraires (et absurdes) comme \u201con met tout au max pour une meilleure qualit\u00e9\u201d (ce que l\u2019on voit plus g\u00e9n\u00e9ralement au sujet des r\u00e8gles MISRA ou des options des outils d\u2019analyse statique de code). Rien de tout cela. Je pr\u00f4ne l\u2019am\u00e9lioration continue et le pragmatisme, c\u2019est dans cette d\u00e9marche que nous allons passer en revue des incr\u00e9ments simples qui b\u00e9n\u00e9ficieront au projet et aux d\u00e9veloppeurs.<\/p>\n\n\n\n<h3>Niveau 1 : l\u2019indispensable<\/h3>\n\n\n\n<p>Par d\u00e9faut, si vous ne pr\u00e9cisez pas d\u2019option de warning particuli\u00e8re, le compilateur v\u00e9rifie bien s\u00fbr des r\u00e8gles relatives au langage mais cette situation est \u00e0 bannir compl\u00e8tement : elle passe \u00e0 c\u00f4t\u00e9 de faiblesses les plus promptes \u00e0 causer des bugs. Aussi, s\u2019il ne devait y avoir qu\u2019une option de warning \u00e0 utiliser, \u00e7a serait -Wall \u2026 qui est loin de les activer tous m\u00eame si elle en rassemble plusieurs dizaines, list\u00e9s dans la page de la documentation de gcc d\u00e9di\u00e9e aux warnings : <a href=\"https:\/\/gcc.gnu.org\/onlinedocs\/gcc\/Warning-Options.html\">https:\/\/gcc.gnu.org\/onlinedocs\/gcc\/Warning-Options.html<\/a>. A propos de cette page, vous aurez souvent \u00e0 vous y r\u00e9f\u00e9rer car j\u2019ai pris le parti de ne pas indiquer la signification de chaque warning \u00e9voqu\u00e9 dans cet article.&nbsp;<\/p>\n\n\n\n<p>Par cette action simple qui doit devenir automatique, vous d\u00e9tecterez ainsi les probl\u00e8mes les plus importants. Et les plus simples \u00e0 r\u00e9gler.<\/p>\n\n\n\n<p>Donc si vous en \u00eates au niveau 0, r\u00e9agissez ! \u00c7a n&#8217;est pas cher et \u00e7a peut rapporter gros. A moins que vous ne pr\u00e9f\u00e9riez subir les bugs. Dans ce cas, vous pouvez vous \u00e9pargner la lecture de la suite de cet article. Mais ne pr\u00e9tendez pas \u00e9crire du code de qualit\u00e9.<\/p>\n\n\n\n<h3>Niveau 2 : le minimum<\/h3>\n\n\n\n<p>Disons que \u201c-Wall\u201d \u00e9tait le strict minimum mais si vous l\u2019utilisiez d\u00e9j\u00e0 habituellement ou si vous avez activ\u00e9 cette option et corrig\u00e9 les warnings trouv\u00e9s (avec dans ce cas une probable satisfaction), vous \u00eates pr\u00eat pour passer la seconde en utilisant le couple -Wall -Wextra.<\/p>\n\n\n\n<p>L\u2019option -Wextra ajoute son lot de warnings (plus d\u2019une quinzaine d\u2019apr\u00e8s la documentation de gcc). Tous ne vont pas mettre au jour des bugs manifestes mais vont alerter sur des faiblesses qui peuvent induire un comportement inattendu : -Wsign-compare, -Wtype-limits, -Wmissing-field-initializers \u2026<\/p>\n\n\n\n<p>Vous pourriez rencontrer l\u2019option -W qui est l\u2019ancienne notation de -Wextra. On peut se demander pourquoi elle n\u2019a pas \u00e9t\u00e9 d\u00e9pr\u00e9ci\u00e9e mais bref \u2026 renommez-l\u00e0 pour \u00eatre plus explicite.<\/p>\n\n\n\n<p>Si -Wextra vous am\u00e8ne beaucoup de warnings, vous \u00eates peut-\u00eatre dans le cas o\u00f9, utilisant abondamment les callbacks, ces warnings sont de type \u201cunused parameter\u201d. Vous pouvez trouver des mani\u00e8res de d\u00e9clarer ces param\u00e8tres comme inutilis\u00e9s dans le code (avec l\u2019attribut unused) ou de les utiliser de mani\u00e8re factice pour satisfaire le compilateur. Ou sinon, d\u00e9sactivez uniquement ce warning avec -Wno-unused-parameter, au moins temporairement. Vous gagnerez en lisibilit\u00e9 pour corriger les warnings restants et adopter une strat\u00e9gie concernant celui-ci. Quoi qu\u2019il en soit, prenez le temps en premier lieu de parcourir chacun des endroits point\u00e9s, cela permettra peut-\u00eatre de trouver des incoh\u00e9rences : \u201ctiens, la fonction marchait alors qu\u2019on n\u2019utilise pas ce param\u00e8tre bien qu\u2019on aurait d\u00fb\u201d ou \u201cah, ce param\u00e8tre n\u2019est r\u00e9ellement plus utilis\u00e9, on l\u2019enl\u00e8ve\u201d.<\/p>\n\n\n\n<h3>Niveau 3 : le recommand\u00e9<\/h3>\n\n\n\n<p>Bravo, en ayant franchi le niveau 2, vous avez int\u00e9gr\u00e9 le fait que d\u00e9sormais -Wall ne sera plus jamais seul car toujours accompagn\u00e9 de son ins\u00e9parable -Wextra (et l\u2019utilisation des deux semble unanimement indiqu\u00e9e). Vous avez \u00e9galement d\u00e9j\u00e0 gagn\u00e9 en confiance, en r\u00e9alisant quels bugs auraient pu se produire ou en constatant un changement de comportement de l\u2019applicatif.<\/p>\n\n\n\n<p>Plus on augmente en niveau, plus les warnings nouveaux portent sur des consid\u00e9rations pr\u00e9cises &#8230; et a priori une dangerosit\u00e9 (ou une probabilit\u00e9) moindre. Aussi, faites en fonction du niveau technique de l\u2019\u00e9quipe, du temps disponible \u00e0 consacrer \u00e0 cela (m\u00eame si \u00e9viter un bug co\u00fbte souvent moins cher que de le corriger apr\u00e8s qu\u2019il se soit manifest\u00e9). Nous souhaitons ici apprendre \u00e0 tirer le meilleur du compilateur, ce qui implique de mettre un pied dans la documentation des options de warnings et de comprendre le r\u00f4le de chacune. C\u2019est essentiel puisqu\u2019il s\u2019agit de faire du sur-mesure d\u00e9sormais.<\/p>\n\n\n\n<p>Vous constaterez que cette approche par les warnings va soulever des probl\u00e9matiques techniques qui vous feront progresser sur de nombreux aspects : lisibilit\u00e9 et maintenabilit\u00e9 du code, s\u00e9curit\u00e9, gestion des pointeurs et des types, connaissance du compilateur, etc.&nbsp;<\/p>\n\n\n\n<p>Voici donc la suite d\u2019options que je vous propose d\u2019adopter :<\/p>\n\n\n\n<p>-Wall -Wextra -Wshadow -Wpointer-arith -Wundef -Wcast-align -Wswitch-default -Wwrite-strings -Wbad-function-cast<\/p>\n\n\n\n<h3>Niveau 4 : l\u2019exigeant<\/h3>\n\n\n\n<p>A ce stade, vous devenez plus fin connaisseur des options du compilateur et vous en comprenez la subtilit\u00e9. Vous pouvez encore en ajouter quelques-unes :<\/p>\n\n\n\n<p>-Wformat=2 -Wcast-qual -Wconversion -Wlogical-op -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations<\/p>\n\n\n\n<p>Ne prenez pas peur. Faites connaissance avec chacune au fur et \u00e0 mesure. Et adaptez si besoin, selon votre code ou votre jugement. Et dites-vous que cette liste est dans les propri\u00e9t\u00e9s du projet, un makefile, \u2026 donc \u00e7a ne change pas vraiment grand chose qu\u2019il y ait 10 options ou 17.<\/p>\n\n\n\n<p>Ensuite, comme toujours, veillez \u00e0 ne pas rendre les choses complexes (comment \u00e7a, c\u2019est trop tard ?). Les options de warnings que vous rajouteriez pourront trouver des d\u00e9fauts potentiels mais en moins grand nombre. Ne mettez pas non plus tous vos \u0153ufs dans le m\u00eame panier, c\u2019est \u00e0 dire qu\u2019il y a sans doute d\u2019autres points d\u2019am\u00e9lioration \u00e0 trouver concernant vos projets : architecture, tests, int\u00e9gration continue, satisfaction des besoins clients, support, correction de bugs \u2026<\/p>\n\n\n\n<p>Pour parachever ce niveau, je vous soumets une suggestion : utilisez de mani\u00e8re alternative un autre compilateur. Typiquement, si par d\u00e9faut vous utilisez gcc, alors mettez en place clang (issu du projet LLVM qui contient d\u2019autres outils incontournables). C\u2019est toujours int\u00e9ressant. Et pour des m\u00eames options de warnings, leur traitement interne sera l\u00e9g\u00e8rement diff\u00e9rent. Cet autre compilateur l\u00e8vera donc quelques warnings inconnus du premier. Une mani\u00e8re de polir son build et son code.<\/p>\n\n\n\n<h3>Niveau 5 : le sur-mesure<\/h3>\n\n\n\n<p>Pour donner un retour d\u2019exp\u00e9rience et \u00eatre tout \u00e0 fait honn\u00eate, je ne crois pas avoir vu de projet d\u00e9passant l\u2019\u00e9quivalent du niveau 3. Alors me direz-vous, pourquoi faire du z\u00e8le et s\u2019acharner ? Et bien pour apprendre, et d\u00e9couvrir ce que les compilateurs peuvent faire pour vous sur ces probl\u00e9matiques. Ils sont capables d\u2019aller trouver des faiblesses sans avoir besoin d\u2019autres outils. Je pense en premier lieu aux outils d\u2019analyse statique de code, terriblement puissants mais qui demandent d\u2019investir financi\u00e8rement (les outils en vue sont tr\u00e8s co\u00fbteux, sinon essayez clang-analyze) et dans la configuration, la maintenance et correction des d\u00e9fauts (qui parfois am\u00e8nent \u00e0 complexifier le code !). Et comme je l\u2019ai d\u00e9j\u00e0 vu, le c\u00f4t\u00e9 pratique n\u2019est pas toujours au rendez-vous quand l\u2019analyse et les r\u00e9sultats sont produits sur un serveur.<\/p>\n\n\n\n<p>Bien, restons-en donc avec notre compilateur. Le fait de rajouter des options de warnings permettra d\u2019am\u00e9liorer votre code (et de trouver encore des probl\u00e8mes) mais au niveau atteint, il peut d\u00e9j\u00e0 y en avoir beaucoup. Il ne faudrait donc pas tomber dans l\u2019indigestion. Il est important de mettre cela en perspective dans votre strat\u00e9gie d\u2019am\u00e9lioration continue.<\/p>\n\n\n\n<p>Dans cette strat\u00e9gie, une des approches concernant l\u2019ajout de nouveaux warnings pourrait \u00eatre de ne pas les activer dans un contexte de d\u00e9veloppement mais de les ajouter dans un job de compilation suppl\u00e9mentaire dans votre int\u00e9gration continue, par exemple.<\/p>\n\n\n\n<p>En consultant la documentation, vous d\u00e9couvrirez que des options peuvent \u00eatre tr\u00e8s utiles mais dans des contextes particuliers : utilisation de flottants (-Wfloat-equal et -Wdouble-promotion), embarqu\u00e9 contraint en m\u00e9moire (-Wframe-larger-than et -Wstack-usage-len), s\u00e9curit\u00e9 sur le formatage de cha\u00eenes (-Wformat-truncation=2 et -Wformat-signedness), propret\u00e9 (-Wdeclaration-after-statement, -Wredundant-decls, -Wmissing-include-dirs, -Wunused-macros), code conditionnel if\/else (-Wduplicated-cond, -Wduplicated-branches), types (-Waggregate-return et -Wshift-overflow=2) &#8230;<\/p>\n\n\n\n<p>Voil\u00e0 pour le sur-mesure commun aux deux compilateurs cit\u00e9s. Mais sachez que clang propose des options bien \u00e0 lui, qui pourraient vous \u00eatre utiles, comme : -Wheader-guard, -Wloop-analysis, -Wstring-conversion, -Wunique-enum &#8230;<\/p>\n\n\n\n<p>A vous de jouer d\u00e9sormais, en suivant la trame donn\u00e9e \u00e0 travers ces 5 niveaux et en adaptant suivant vos besoins, vos souhaits et vos ressources.<\/p>\n\n\n\n<h3><strong>Utiliser ou pas l\u2019option -Werror ?<\/strong><\/h3>\n\n\n\n<p>Voil\u00e0 qui fait d\u00e9bat. Cette option permet de consid\u00e9rer les warnings comme des erreurs, la cons\u00e9quence directe \u00e9tant l\u2019arr\u00eat de la compilation \u00e0 la premi\u00e8re occurrence.<\/p>\n\n\n\n<p>Aussi, une fois atteint le niveau de warnings choisi et que tous ont \u00e9t\u00e9 \u00e9radiqu\u00e9s, l\u2019utilisation de cette option peut \u00eatre vue comme un rempart contre une nouvelle prolif\u00e9ration insidieuse, lente mais continue, de nouveaux warnings. Ces derniers sont corrig\u00e9s d\u00e8s leur apparition et ainsi, le code fourni est garanti exempt de warnings. Cela semble donc plus rigoureux.<\/p>\n\n\n\n<p>Mon avis semble \u00eatre minoritaire sur la question mais je ne suis pas particuli\u00e8rement favorable \u00e0 cette option. Tout d\u2019abord, l\u2019\u00e9mission de warnings d\u00e9pend du compilateur et de sa version, il est donc p\u00e9nalisant quand on arrive sur un projet par exemple, de voir la compilation \u00e9chouer. De m\u00eame, il peut arriver qu\u2019en int\u00e9grant une application dans un syst\u00e8me de build comme Yocto (qui aurait par d\u00e9faut des options plus rigoureuses), cela emp\u00eache carr\u00e9ment de g\u00e9n\u00e9rer l\u2019image finale.<\/p>\n\n\n\n<p>D\u2019autre part, de nombreux warnings vont demander du temps et des discussions parce que leur correction ne sera pas imm\u00e9diate et qu\u2019elle pourrait n\u00e9cessiter des changements plus profonds ou la r\u00e9daction de r\u00e8gles communes de programmation.<\/p>\n\n\n\n<p>Un autre cas concret p\u00e9nible arrive quand on est en train de modifier du code (qui ne va parfois pas rester) et d\u2019\u00e9chouer sur un probl\u00e8me inoffensif comme l\u2019ajout de la d\u00e9claration d\u2019une variable au milieu du code avec -Wdeclaration-after-statement &#8230;<\/p>\n\n\n\n<p>Plus on pousse les options, plus il sera facile de causer de nouveaux warnings \u2026 et donc de se prendre les pieds dans le tapis avec -Werror. Tous les warnings ne se valent pas en terme de gravit\u00e9. L\u2019utilisation de -Werror peut aussi d\u00e9pendre du niveau de warning : il peut s\u2019av\u00e9rer d\u2019autant plus utile que le niveau des warnings est faible. Avec un niveau \u00e9lev\u00e9, cela devient g\u00eanant, voire p\u00e9nalisant.<\/p>\n\n\n\n<p>Ce qui est d\u00e9terminant, c\u2019est que les warnings ne soient pas oubli\u00e9s ! Pourquoi ne pas faire en sorte d\u2019ajouter cette option sur compilation de pr\u00e9-commit ou dans l\u2019int\u00e9gration continue (o\u00f9 rendre visible les warnings est d\u00e9j\u00e0 tr\u00e8s instructif et visuel) ?<\/p>\n\n\n\n<p>Emparez-vous de cette question, d\u00e9battez-en \u2026 et choisissez.<\/p>\n\n\n\n<h3>Conclusion<\/h3>\n\n\n\n<p>Les compilateurs (et les warnings) sont nos amis. Nous les utilisons tous les jours mais ils ne demandent qu\u2019\u00e0 s\u2019exprimer davantage. On a tout \u00e0 gagner \u00e0 mieux conna\u00eetre les options et \u00e0 les utiliser. Cela demande un effort mais cet investissement sera vite rentabilis\u00e9.<\/p>\n\n\n\n<p>Concernant les options de warnings, nous avons pr\u00e9sent\u00e9 une approche qui permet de renforcer leur usage de mani\u00e8re progressive, en 5 niveaux, au cours desquels une liste croissante d\u2019options a \u00e9t\u00e9 propos\u00e9e. Ces suggestions sont \u00e0 adapter en fonction du contexte du projet dans lequel elles seront mises en \u0153uvre. Quoi qu\u2019il en soit, vous avez d\u00fb trouver des \u00e9l\u00e9ments pour vous guider dans cette progression, de la prise de conscience \u00e0 la ma\u00eetrise des warnings. Vous saurez donc d\u00e9cider en toute connaissance de cause (sinon, je peux bien s\u00fbr vous accompagner sur ces sujets).<\/p>\n\n\n\n<p>Pour trouver des faiblesses et bugs dans vos logiciels, le sujet trait\u00e9 n\u2019en est qu\u2019un parmi d\u2019autres. Les compilateurs proposent d\u2019autres fonctionnalit\u00e9s comme les sanitizers qui instrumentent le code pour d\u00e9tecter des erreurs \u00e0 l\u2019ex\u00e9cution, des options de durcissement (-fstack-protector-strong, &nbsp;-D_FORTIFY_SOURCE=2, etc.) \u2026 D\u2019autres outils vous permettront d\u2019avoir du code plus lisible, mieux format\u00e9 (clang-format) et plus conforme (votre IDE, clang-tidy \u2026).<\/p>\n\n\n\n<p>Au-del\u00e0 des compilateurs, l\u2019am\u00e9lioration des logiciels repose aussi sur d\u2019autres outils et pratiques : tests, int\u00e9gration continue, revue de code, gestion des t\u00e2ches \u2026 Nous sommes all\u00e9s loin dans les warnings mais pensez bien \u00e0 l\u2019\u00e9quilibre de tous ces sujets dans la vie de vos projets et ajustez les curseurs en cons\u00e9quence. Rien ne sert d\u2019avoir du code qui compile sans un warning apr\u00e8s avoir ajout\u00e9 des dizaines d\u2019options si par exemple il ne r\u00e9pond pas correctement aux besoins sp\u00e9cifi\u00e9s.<\/p>\n\n\n\n<p>Avancez progressivement, ayez une vision globale, soyez pragmatique. Mais consid\u00e9rez les warnings \u00e0 leur juste valeur, et incluez les dans votre strat\u00e9gie de d\u00e9veloppement, sans vous habituer \u00e0 leur pr\u00e9sence en disant \u201con verra plus tard, ils ont toujours \u00e9t\u00e9 l\u00e0 et tout fonctionne bien\u201d.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Ces derni\u00e8res ann\u00e9es, les compilateurs ont \u00e9norm\u00e9ment progress\u00e9 sur diff\u00e9rents aspects : optimisation (g\u00e9n\u00e9ration de code, LTO, \u2026), instrumentation (sanitizers), debug, vectorisation, \u2026 mais \u00e9galement concernant un sujet plus imm\u00e9diat et visible au quotidien : les warnings, que \u00e7a soit dans la d\u00e9tection des probl\u00e8mes ou la mani\u00e8re dont ils sont libell\u00e9s (pr\u00e9cision, suggestion, rappel [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":[],"_links":{"self":[{"href":"https:\/\/optimum-software.fr\/index.php?rest_route=\/wp\/v2\/pages\/20"}],"collection":[{"href":"https:\/\/optimum-software.fr\/index.php?rest_route=\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/optimum-software.fr\/index.php?rest_route=\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/optimum-software.fr\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/optimum-software.fr\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=20"}],"version-history":[{"count":4,"href":"https:\/\/optimum-software.fr\/index.php?rest_route=\/wp\/v2\/pages\/20\/revisions"}],"predecessor-version":[{"id":25,"href":"https:\/\/optimum-software.fr\/index.php?rest_route=\/wp\/v2\/pages\/20\/revisions\/25"}],"wp:attachment":[{"href":"https:\/\/optimum-software.fr\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=20"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}