NSI · Terminale

La pile d'exécution (Call Stack) et mécanisme interne

Comprendre le fonctionnement de la pile d'appels, l'empilement/dépilement pas à pas (fctA/fctB), la portée des variables et le risque de débordement RecursionError.

La Pile d'Exécution (Call Stack) & Mécanisme Interne

Pour comprendre comment l'ordinateur exécute les fonctions récursives, nous devons comprendre le fonctionnement de la pile d'exécution (Call Stack).

1. Activité d'observation : Deux fonctions qui s'appellent

Activité

Activité 1 — Deux fonctions qui s'appellent

Analysez puis testez le programme suivant :

Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
def fctA():
print("Début fonction fctA")
i = 0
while i < 5:
print(f"fctA {i}")
i = i + 1
print("Fin fonction fctA")
def fctB():
print("Début fonction fctB")
i = 0
while i < 5:
if i == 3:
fctA()
print("Retour à la fonction fctB")
print(f"fctB {i}")
i = i + 1
print("Fin fonction fctB")
fctB()

Sortie observée dans la console :

Console / Sortie
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Début fonction fctB
fctB 0
fctB 1
fctB 2
Début fonction fctA
fctA 0
fctA 1
fctA 2
fctA 3
fctA 4
Fin fonction fctA
Retour à la fonction fctB
fctB 3
fctB 4
Fin fonction fctB

2. Le Mécanisme d'Interruption et de Pile d'Appels

Dans l'exemple ci-dessus, nous avons une fonction (fctB) qui appelle une autre fonction (fctA).

La principale chose à retenir de cet exemple est que l'exécution de `fctB` est interrompue pendant l'exécution de `fctA`. Une fois l'exécution de fctA terminée, l'exécution de fctB reprendra là où elle avait été interrompue.

Pour gérer ces fonctions qui appellent d'autres fonctions, le système utilise une pile d'exécution (Call Stack). Une pile d'exécution permet d'enregistrer des informations sur les fonctions en cours d'exécution dans un programme. On parle de pile, car les exécutions successives « s'empilent » les unes sur les autres.

Si nous nous intéressons à la pile d'exécution du programme étudié ci-dessus, nous obtenons le schéma suivant :

Fonctionnement de la pile d'exécutionFonctionnement de la pile d'exécution

À retenir / Remarque

Expérimenter avec le simulateur interactif

Visualisez en direct l'empilement et le dépilement des appels de fonctions sur la pile d'exécution : Ouvrir le Simulateur de Récursivité (Pile d'Appels & Arbre)→

Définition

Portée locale des variables

Les variables définies à l'intérieur d'une fonction sont locales à son cadre d'exécution. Même si deux fonctions possèdent une variable portant le même nom (par exemple i ou n), elles correspondent à des adresses mémoires distinctes et indépendantes dans la pile.

3. Risque de Récursion Infinie et Erreur de Dépassement (RecursionError)

Que se passe-t-il si une fonction récursive ne possède pas de cas de base, ou si son argument ne converge jamais vers la condition d'arrêt ?

Activité

Activité 2 — La récursion sans fin

Testez le code suivant :

Python
1
2
3
4
5
6
def boucle_infinie(n: int):
print(f"Appel n = {n}")
return boucle_infinie(n + 1) # Pas de cas de base !
# Décommentez pour tester l'erreur :
# boucle_infinie(1)

Résultat dans la console Python :

Console / Sortie
1
RecursionError: maximum recursion depth exceeded while calling a Python object
À retenir / Remarque

Pourquoi cette erreur survient-elle ?

Chaque appel de fonction consomme un espace mémoire dans la pile d'appels. Si les appels s'enchaînent indéfiniment, la mémoire allouée à la pile est saturée : on parle de débordement de pile (Stack Overflow).

En Python, la profondeur maximale de récursion est par défaut limitée à 1000 appels (consultable via sys.getrecursionlimit()) pour protéger le système d'exploitation contre les plantages.

Avez-vous compris et assimilé ce cours ?

+50 XP

Étudiez le contenu activement pendant au moins 45 secondes pour pouvoir débloquer la validation au mérite.

Temps d'étude actif :0s / 45s