Conclusion
Cette présentation a montré qu’en C, beaucoup d’erreurs graves ne se manifestent pas immédiatement par un crash clair ou par un message du compilateur. Fuites mémoire, dépassements de tampon, lectures de mémoire non initialisée, transtypages douteux et comportements indéfinis peuvent rester silencieux, puis provoquer des corruptions difficiles à diagnostiquer.
Les exemples étudiés montrent également que le comportement observé dépend fortement du compilateur, des optimisations actives, de l’état de la mémoire, de l’architecture et du contexte d’exécution. Un programme qui “semble fonctionner” n’est donc pas nécessairement un programme correct ou sûr.
La conclusion opérationnelle est simple : produire du code sûr en C ne consiste pas seulement à faire compiler un programme, mais à multiplier les vérifications, comprendre les limites du langage, instrumenter régulièrement les binaires de test, et intégrer ces outils dans une vraie démarche de validation. Les sanitizers, Valgrind et le fuzzing ne remplacent pas la conception rigoureuse, mais ils rendent visibles des défauts qui, sans eux, resteraient enfouis jusqu’au moment de l’incident.
Combiner les sanitizer
En pratique, les sanitizers ne se combinent pas tous proprement entre eux. Certains couples sont compatibles et utiles, mais beaucoup d’outils reposent sur des mécanismes d’instrumentation ou de shadow memory distincts, ce qui impose de réaliser plusieurs compilations et plusieurs campagnes de test séparées.
Sur le périmètre présenté ici, GCC couvre principalement AddressSanitizer, ThreadSanitizer, UndefinedBehaviorSanitizer et LeakSanitizer. Clang couvre lui aussi ces outils, mais ajoute notamment MemorySanitizer et TypeSanitizer, ce qui explique pourquoi certains exemples de cette présentation n’étaient réalistes qu’avec Clang. TypeSanitizer reste par ailleurs documenté comme expérimental dans la famille Clang/LLVM.
Il faut donc raisonner en campagne d’analyse plutôt qu’en compilation unique : une passe ASan/LSan pour les erreurs mémoire classiques, une passe MSan pour les usages de mémoire non initialisée, une passe UBSan pour les comportements indéfinis, puis éventuellement une passe TySan pour les violations de type. À noter qu’un cas utile existe tout de même : LeakSanitizer peut être combiné avec AddressSanitizer, ce qui permet d’obtenir à la fois la détection d’erreurs mémoire et la détection de fuites dans une même exécution.
Valgrind et sanitizer
Valgrind et les sanitizers poursuivent un objectif proche — rendre visibles des erreurs qui resteraient sinon silencieuses — mais leur mécanique interne est très différente. Les sanitizers instrumentent le code à la compilation, alors que Valgrind instrumente dynamiquement le binaire à l’exécution.
Dans une démarche pratique, il vaut mieux éviter de lancer sous Valgrind un binaire déjà instrumenté par un sanitizer lourd reposant sur une shadow memory, comme ASan, MSan, TSan ou TySan. Superposer deux mécanismes de suivi mémoire revient souvent à exploser l’empreinte mémoire, à ralentir fortement l’exécution et à dégrader la lisibilité du diagnostic. Ce n’est pas une méthode robuste pour analyser proprement un programme.
La bonne approche consiste plutôt à séparer les usages : utiliser les sanitizers sur des binaires recompilés pour obtenir des diagnostics ciblés et rapides, puis utiliser Valgrind sur un binaire non instrumenté lorsque l’on veut un contrôle plus global, une analyse sans recompilation, ou une intégration avec GDB et ses commandes de diagnostic. Valgrind reste par ailleurs une suite d’outils complète, Memcheck n’étant que l’outil le plus connu parmi d’autres comme Massif, Callgrind, Helgrind ou DRD.
Références
| Ref. | Source | Type | Utilisation dans la présentation |
|---|---|---|---|
| [1] | MISC Hors-Série n°34, février/mars 2026, dossier consacré aux sanitizers, à Valgrind, au fuzzing et à l’intégration avec les débogueurs. | Presse technique / source principale | Base conceptuelle de la présentation, exemples de code, organisation des thèmes, comparaisons entre outils et commentaires sur leurs limites. |
| [2] |
ISO/IEC 9899, langage C et bibliothèque standard C
(stdlib.h, stdio.h, limits.h, etc.).
|
Norme / référence de langage | Référence de fond pour la gestion mémoire, les conversions, les types, les comportements indéfinis et les fonctions standard utilisées dans les exemples. |
| [3] | GCC documentation, Instrumentation Options. | Documentation compilateur |
Vérification des options -fsanitize disponibles dans GCC,
de certaines incompatibilités entre sanitizers et des recommandations
d’usage côté compilation.
|
| [4] | Clang / LLVM documentation, pages AddressSanitizer, MemorySanitizer, UndefinedBehaviorSanitizer, LeakSanitizer, TypeSanitizer et index général. | Documentation compilateur | Vérification du périmètre des sanitizers disponibles côté Clang, du rôle de TypeSanitizer, ainsi que des possibilités de combinaison comme ASan + LSan. |
| [5] | Valgrind Documentation, manuel utilisateur et documentation du cœur. | Documentation outil | Référence pour le rôle de Memcheck, les autres outils de la suite, les options d’exécution et l’usage conjoint avec GDB/vgdb. |
| [6] | OpenAI, documentation et pages produit autour de ChatGPT / GPT-5.4 Thinking. | Assistant IA / source secondaire | Assistance à la structuration, à la reformulation, à la synthèse et à la mise en forme pédagogique de certains contenus de cette présentation. La dénomination correcte du modèle est GPT-5.4 Thinking. |