Débogage avancé/Travail pratique/Pile d'appels
But de ce TP
[modifier | modifier le wikicode]Souvent, un bug est détecté à l'exécution d'une fonction A qui a été appelée par la fonction B qui a provoqué le bug. Il est donc important de pouvoir remonter dans la pile d'appel pour observer l'état de la fonction B.
Ce TP concerne la compréhension de la pile d'appels des fonctions dans un programme impératif. Il permet aussi de réviser quelques bases sur les débogueurs (afficher le code dans un terminal, lancer le programme, mettre un point d'arrêt, se déplacer dans la pile d'appel, terminer).
N'hésiter pas à regarder la solution en faisant les manipulations si vous souhaitez plutôt un mini-tutoriel GDB en mode terminal.
Le code à déboguer
[modifier | modifier le wikicode]Créer un fichier bug_assert.c contenant le code suivant.
#include <assert.h>
#include <stdbool.h> // inutile pour C23
#include <stdlib.h>
int main() {
assert(false); // echec ici
return EXIT_SUCCESS; // la macro vaut 0
}
Les consignes
[modifier | modifier le wikicode]- Compiler et lancer le programme
./bug_assert
. Vous devriez voir le message d'erreur dans votre terminal qui donne la ligne et le fichier du programme qui a détecté le prédicat a faux. - Lancer gdb avec le programme en argument dans un terminal. Demandé à gdb d'afficher le code du programme à déboguer. Mettre un point d'arrêt sur la fonction
main
. Démarrer. Vous devriez être au début dumain
. Continuer. À l'assertion, afficher la pile d'appel et remonter dans la pile d'appel de fonction jusqu'au code source impliquéassert(false);
.
Vous devriez avoir tapé les commandes suivantes (les affichages de GDB sont omis):
$ gcc -o bug_assert bug_assert.c -g -Wall -Wextra -fanalyzer
$ ./bug_assert
bug_assert: /home/greg/ensimag-rappeldec.github/src/bugs/bug_assert.c:20: main: Assertion `false' failed.
Abandon (core dumped)
$ gdb ./bug_assert
[...]
(gdb) layout src
(gdb) break main
(gdb) run
(gdb) cont
(gdb) where
(gdb) up # le nombre de up pour arriver au main varie
(gdb) up
(gdb) up
(gdb) up
(gdb) quit # confirmez la terminaison