🔝 Retour au Sommaire
🎯 Niveau : Avancé
Ce module couvre les outils de diagnostic — ce qui vous permet de trouver les bugs, les fuites mémoire, les hotspots de performance, et les problèmes de qualité de code avant qu'ils n'atteignent la production. GDB, quatre sanitizers (Address, UndefinedBehavior, Thread, Memory), Valgrind, Massif, perf, flamegraphs, clang-tidy, cppcheck, clang-format. Chaque outil a un rôle précis et des contraintes d'utilisation spécifiques — les combiner incorrectement produit des résultats faux ou aucun résultat.
- Déboguer un programme C++ avec GDB : breakpoints conditionnels, watchpoints, inspection de la mémoire, core dumps pour le post-mortem debugging.
- Instrumenter le code avec les quatre sanitizers (ASan, UBSan, TSan, MSan) et interpréter leurs rapports.
- Détecter les fuites mémoire et les erreurs d'accès avec Valgrind (memcheck) et profiler les allocations heap avec Massif.
- Profiler la performance CPU avec
perf(sampling, compteurs matériels) et visualiser les résultats avec des flamegraphs. - Configurer clang-tidy et cppcheck pour l'analyse statique, et clang-format pour le formatage automatique.
- Intégrer ces outils dans le workflow de développement quotidien (CMake, IDE, pre-commit).
- Module 2, chapitre 5 : gestion mémoire manuelle (stack, heap, pointeurs) — nécessaire pour comprendre ce que Valgrind et AddressSanitizer détectent.
- Module 7, chapitre 21 : threads et concurrence — nécessaire pour exploiter ThreadSanitizer et comprendre ses rapports de data races.
- Module 9, chapitre 26 : CMake — les sanitizers, Valgrind, la couverture de code et l'analyse statique s'intègrent dans le build system via des target properties et des CMake Presets.
- Module 1, chapitre 2, section 2.6 : options de compilation (
-g,-O0,-O2) — le choix du niveau d'optimisation et des symboles de debug conditionne l'utilisabilité de chaque outil.
Débogage interactif avec GDB, intégration IDE, analyse post-mortem via core dumps, et les quatre sanitizers du compilateur. Ce chapitre est l'outil de premier recours quand un programme se comporte incorrectement.
- GDB : commandes de navigation (
run,step,next,continue,finish), inspection (print,display,watch,info locals,info threads), breakpoints conditionnels (break file.cpp:42 if count > 100), watchpoints sur les variables. - Débogage via IDE : configuration de launch.json (VS Code) et des run configurations (CLion), intégration GDB/LLDB transparente, conditional breakpoints visuels.
- Core dumps : activation (
ulimit -c unlimited), analyse post-mortem avecgdb ./program core, extraction de la stack trace et de l'état des variables au moment du crash. - Sanitizers : AddressSanitizer (
-fsanitize=address— buffer overflow, use-after-free, stack overflow), UndefinedBehaviorSanitizer (-fsanitize=undefined— signed overflow, null deref, misaligned access), ThreadSanitizer (-fsanitize=thread— data races), MemorySanitizer (-fsanitize=memory— lecture de mémoire non initialisée, Clang uniquement). std::stacktrace(C++23) : intégration des traces d'exécution dans le code de débogage, complémentaire aux sanitizers.
Détection et diagnostic des problèmes mémoire en profondeur. Valgrind est l'outil de référence pour les fuites et les accès invalides ; Massif profiler les allocations heap pour identifier les consommateurs de mémoire.
- Valgrind memcheck : détection de fuites (
definitely lost,indirectly lost,possibly lost,still reachable), accès invalides (read/write après free, buffer overflow), lectures de mémoire non initialisée. Overhead : ~20x ralentissement. - Lecture des rapports Valgrind : interprétation des stack traces, suppression des faux positifs avec les fichiers
.supp, intégration dans les tests automatisés. - Massif : heap profiling — visualisation de l'évolution des allocations dans le temps, identification des fonctions qui consomment le plus de mémoire,
ms_printpour les rapports texte. - Memory leaks : stratégies de détection et de résolution — pattern d'investigation, corrélation avec le code source, vérification post-fix.
Identification des hotspots CPU et optimisation guidée par les données. Ce chapitre couvre perf (le profiler standard de Linux), gprof (historique), et la visualisation avec des flamegraphs.
perf recordetperf report: sampling statistique — enregistrement des échantillons CPU, rapport par fonction et par ligne source. Avantage : overhead minimal (~2%), profiling de code en production possible.perf stat: compteurs matériels (cache misses, branch mispredictions, instructions per cycle) — diagnostic de problèmes de localité mémoire et de prédiction de branchement.- gprof : profiling par instrumentation (
-pg) — comptage exact des appels de fonctions. Limitation : overhead plus élevé, incompatible avec certaines optimisations, approche historique. - Flamegraphs : visualisation hiérarchique des profils
perf— identification visuelle immédiate des chemins chauds. Génération avec les scripts de Brendan Gregg ou l'outil Hotspot. - Hotspot : interface graphique pour les données
perf, alternative visuelle àperf report.
Détection de bugs et de mauvaises pratiques sans exécuter le code. clang-tidy pour l'analyse sémantique, cppcheck pour les erreurs classiques, clang-format pour imposer un style uniforme.
- clang-tidy : analyse statique moderne intégrée à l'écosystème LLVM. Configuration via
.clang-tidy(fichier YAML), checks organisés par catégorie (bugprone-*,modernize-*,performance-*,readability-*,cppcoreguidelines-*). Checks recommandés comme point de départ minimal. - cppcheck : détection d'erreurs classiques (null pointer dereference, division par zéro, buffer overflow statiquement détectable) — complémentaire à clang-tidy, moins de faux positifs.
- clang-format 19 : formatage automatique basé sur un fichier
.clang-format, styles prédéfinis (LLVM, Google, Chromium, Mozilla) ou style personnalisé. Garantit un formatage uniforme sans débat. - Intégration dans le workflow : exécution automatique via CMake custom targets, intégration IDE (VS Code, CLion), pre-commit hooks (préparation pour le Module 17, chapitre 47).
-
Optimisation
-O2/-O3qui rend GDB inutilisable. Le compilateur réordonne les instructions, élimine les variables, inline les fonctions — le debugger ne peut plus mapper le code machine au code source. Les variables apparaissent comme<optimized out>, les breakpoints se déclenchent à des lignes inattendues. Solution : utiliser-Og(optimisations compatibles avec le debug, GCC) ou-O0pour le débogage. Pour profiler du code optimisé, gardez-O2mais ajoutez-gpour conserver les symboles (voir point suivant). -
Valgrind et AddressSanitizer utilisés simultanément. Les deux outils instrumentent les accès mémoire mais de manière incompatible — Valgrind fonctionne par émulation binaire, ASan par instrumentation à la compilation. Les lancer ensemble produit des faux positifs, des crashes, ou une détection dégradée. Utilisez-les séparément : ASan dans le build de développement (plus rapide, overhead ~2x), Valgrind pour les analyses approfondies (memcheck, Massif, overhead ~20x). De même, TSan et ASan sont mutuellement exclusifs — un build par sanitizer.
-
perfsans symboles de débogage.perf record/perf reportsans symboles affiche des adresses hexadécimales au lieu des noms de fonctions. Même en build Release, ajoutez-g(ou-g1pour les symboles minimaux) pour queperfpuisse résoudre les symboles. Sur les librairies système, installez les paquets-dbgsym(sudo apt install libc6-dbg). Sans symboles, un flamegraph est illisible. -
clang-tidy trop verbeux sans configuration. Lancer clang-tidy sans fichier
.clang-tidyactive tous les checks par défaut — des centaines de warnings sur un projet existant, dont beaucoup de faux positifs ou de suggestions non pertinentes. Le résultat est inutilisable et décourage l'adoption. Partez d'un.clang-tidyminimal avec quelques catégories (bugprone-*,performance-*,modernize-use-override) et étendez progressivement. Un outil de qualité qui n'est pas utilisé parce qu'il est trop bruyant ne sert à rien.
À l'issue de ce module, vous savez :
- Déboguer un programme C++ avec GDB (breakpoints conditionnels, watchpoints, core dumps) et via l'IDE.
- Utiliser les quatre sanitizers (ASan, UBSan, TSan, MSan) sur les bons builds, sans les combiner de manière incompatible.
- Détecter et résoudre les fuites mémoire avec Valgrind memcheck, et profiler les allocations avec Massif.
- Profiler la performance CPU avec
perf, lire les compteurs matériels avecperf stat, et générer des flamegraphs exploitables. - Configurer clang-tidy avec un
.clang-tidyadapté au projet, et clang-format pour un formatage uniforme. - Intégrer ces outils dans CMake et dans le workflow de développement (IDE, pre-commit).