Produire une trace d'exécution
Si un as un morceau de code, on peut souhaiter savoir dans quel ordre les instructions sont exécutées.
Pour cela, on peut utiliser un outil de traçage.
Principe
On veut accomplir 2 éléments principaux:
- indiquer quelles lignes de code s'exécutent dans quel ordre
- indiquer les effets de chaque ligne de code
Exemple simple
Si on a le code suivant:
val a = 3 + 4
val b = a * 2
println("salut " + b)
Trace
On aura la trace suivante:
ligne exécutée | effet |
---|---|
val a = 3 + 4 | a: 7 |
val b = a * 2 | a: 7, b: 14 |
println("salut " + b) | a: 7, b: 14, affiche "salut 14" |
Dans le cas d'une séquence d'instructions, on peut voir que les instructions sont exécutées dans l'ordre de lecture du code. Simple!
Le code markdown de ce tableau est disponible ici.
Exemple avec boucle
Si on a le code suivant:
for (i in 1..3){
if (i % 2 == 0) {
println("c'est pair " + i)
}
else {
println("ah ben ah ben, c'est impair " + i)
}
}
Trace
On aura la trace suivante:
ligne exécutée | effet |
---|---|
for (i in 1..3) | i parcourt l'interval 1, 2, 3 |
if (i % 2 == 0) | i: 1 i%2 vaut 1 |
println("ah ben ah ben, c'est impair " + i) | i: 1 affiche "ah ben ah ben, c'est impair 1" |
if (i % 2 == 0) | i: 2 i%2 vaut 0 |
println("c'est pair " + i) | i: 2 affiche "c'est pair 2" |
if (i % 2 == 0) | i: 3 i%2 vaut 1 |
println("ah ben ah ben, c'est impair " + i) | i: 3 affiche "ah ben ah ben, c'est impair 3" |
On voit que:
- on n'indique que les lignes qui s'exécutent en vrai
- certaines lignes s'exécutent plusieurs fois, c'est le principe de la boucle!
- on appelle ce cheminement le flot de contrôle
Exemple avec une fonction
Si on a le code suivant:
fun ma_fonction(a : Int, b: Int) : Int {
val c = a + b
return c
}
fun main() {
var mavariable = 3
var tavariable = 5
var z = ma_fonction(mavariable, tavariable)
var y = ma_fonction(4, 9)
print("z vaut " + z + " et y vaut " + y)
}
Trace
S'il y a des fonctions dans le code, on doit ajouter la pile d'appels pour indiquer quelles fonctions ont été commencées mais pas finies.
ligne exécutée | effet | pile d'appels |
---|---|---|
var mavariable = 3 | mavariable: 3 | main |
var tavariable = 5 | mavariable: 3 tavariable: 5 | main |
var z = ma_fonction(mavariable, tavariable) | mavariable: 3 tavariable: 5 appelle ma_fonction avec a→3 et b→5 | main |
val c = a + b | a: 3 b: 5 c: 8 | ma_fonction main |
return c | a: 3 b: 5 c: 8, retourne 8, z = 8 | ma_fonction main |
var y = ma_fonction(4, 9) | mavariable: 3 tavariable: 5 z: 8 appelle ma_fonction avec a→4 et b→9 | main |
val c = a + b | a: 4 b: 9 c: 13 | ma_fonction main |
return c | a: 4 b: 9 c: 13 retourne 13, y = 13 | ma_fonction main |
println("z vaut " + z + " et y vaut " + y) | mavariable: 3 tavariable: 5 z: 8 y = 13 affiche "z vaut 8 et y vaut 13" | main |
Dans ce cas, on doit ajouter la pile d'appels pour indiquer quelles fonctions ont été commencées mais pas finies.
Valider ta trace
Afin de valider ta trace, tu vas utiliser le débogueur de ton IDE préféré.
- place un point d'arrêt sur la première ligne qui s'exécute
- lance l'exécution en mode débogage
- saute d'une ligne en une ligne pour voir si ta trace est correcte
Si tu te rends à la fin de l'exécution et que toutes tes valeurs étaient bonnes, tu as bien compris ce que fait le code.