diff --git a/Theorie/C/S3-src/fact.c b/Theorie/C/S3-src/fact.c
index 2ea01e9c3c44e7fa686d140e4029bbc9c7f000fd..201dbcb09215593fdbd9c74efa065be7a87f0da3 100644
--- a/Theorie/C/S3-src/fact.c
+++ b/Theorie/C/S3-src/fact.c
@@ -35,8 +35,6 @@ int fact(int n) {
 void compute() {
   int nombre=3;
   int f;
-  printf("La fonction fact est à l'adresse : %p\n",fact);
-  printf("La fonction times est à l'adresse : %p\n",times);
   printf("La variable nombre vaut %d et est à l'adresse %p\n",nombre,&nombre);
   f=fact(nombre);
   printf("La factorielle de %d vaut %d\n",nombre,f);
@@ -79,4 +77,3 @@ int main(int argc, char *argv[]) {
 
   return(EXIT_SUCCESS);
 }
-
diff --git a/Theorie/C/S3-src/fact.out b/Theorie/C/S3-src/fact.out
index c2698ff8d11222fd32a4b8b1c39b581a87a69a6e..ec35110468a0cf0c08c5a9f930bfaafc9615acc6 100644
--- a/Theorie/C/S3-src/fact.out
+++ b/Theorie/C/S3-src/fact.out
@@ -4,8 +4,6 @@ La variable locale f est à l'adresse : 0x7fff5fbfe1dc
 La fonction main est à l'adresse : 0x100000b6b
 La fonction max est à l'adresse : 0x100000b46
 ///FACT
-La fonction fact est à l'adresse : 0x100000a0f
-La fonction times est à l'adresse : 0x1000009d8
 La variable nombre vaut 3 et est à l'adresse 0x7fff5fbfe1ac
 [fact(3)]: Valeur de n:3, adresse: 0x7fff5fbfe17c
 [fact(3)]: appel à fact(2)
diff --git a/Theorie/C/linker.rst b/Theorie/C/linker.rst
index 03a2495e536ea61d50a91a1e5c91d4aed9d5db34..8da9e02fb718d89751294986b3fd1b9c7ea88402 100644
--- a/Theorie/C/linker.rst
+++ b/Theorie/C/linker.rst
@@ -12,8 +12,8 @@ Compléments de C
 Dans les sections précédentes, nous n'avons pas pu couvrir l'ensemble des concepts avancés qui sont relatifs à une bonne utilisation du langage C. Cette section contient quelques notions plus avancées qui sont importantes en pratique.
 
 
-Pointeurs
----------
+Pointeurs avancés
+-----------------
 
 Les pointeurs sont très largement utilisés dans les programmes écrits en langage C. Nous avons utilisé des pointeurs vers des types de données primitifs tel que les ``int``, ``char`` ou ``float`` et des pointeurs vers des structures. En pratique, il est possible en C de définir des pointeurs vers n'importe quel type d'information qui est manipulée par un programme C.
 
@@ -242,6 +242,3 @@ A titre d'exemple, le programme ci-dessous utilise `strerror(3)`_ pour afficher
 
 
 .. [#frestrict] ``restrict`` est également parfois utilisé pour indiquer des contraintes sur les pointeurs passés en argument à une fonction [Walls2006]_.
-
-
-
diff --git a/Theorie/C/malloc.rst b/Theorie/C/malloc.rst
index b640221b92bb0d554c1cd8454ccb3e09fdac52b4..48c535994dfe9a0e406d1b1154ad6582bc6615e0 100644
--- a/Theorie/C/malloc.rst
+++ b/Theorie/C/malloc.rst
@@ -136,71 +136,139 @@ Lors de l'exécution d'un programme en mémoire, le système d'exploitation char
 
    Organisation d'un programme Linux en mémoire
 
-La figure ci-dessus présente une vision schématique de la façon dont un processus Linux est organisé en mémoire centrale. Il y a d'abord une partie de la mémoire qui est réservée au système d'exploitation (OS dans la figure). Cette zone est représentée en grisé dans la figure.
+La figure ci-dessus présente une vision schématique de la façon dont un processus Linux est organisé en mémoire centrale. Dans le cadre de ce cours, nous nous concentrerons sur les zones du Stack et du Heap.
 
-Le segment text
----------------
+.. Il y a d'abord une partie de la mémoire qui est réservée au système d'exploitation (OS dans la figure). Cette zone est représentée en grisé dans la figure.
 
-La première zone est appelée par convention le :term:`segment text`. Cette zone se situe dans la partie basse de la mémoire [#fetext]_. C'est dans cette zone que sont stockées toutes les instructions qui sont exécutées par le micro-processeur. Elle est généralement considérée par le système d'exploitation comme étant uniquement accessible en lecture. Si un programme tente de modifier son :term:`segment text`, il sera immédiatement interrompu par le système d'exploitation. C'est dans le segment text que l'on retrouvera les instructions de langage machine correspondant aux fonctions de calcul et d'affichage du programme. Nous en reparlerons lorsque nous présenterons le fonctionnement du langage d'assemblage.
+..
+    Le segment text
+    ---------------
 
-Le segment des données initialisées
------------------------------------
+    La première zone est appelée par convention le :term:`segment text`. Cette zone se situe dans la partie basse de la mémoire [#fetext]_. C'est dans cette zone que sont stockées toutes les instructions qui sont exécutées par le micro-processeur. Elle est généralement considérée par le système d'exploitation comme étant uniquement accessible en lecture. Si un programme tente de modifier son :term:`segment text`, il sera immédiatement interrompu par le système d'exploitation. C'est dans le segment text que l'on retrouvera les instructions de langage machine correspondant aux fonctions de calcul et d'affichage du programme. Nous en reparlerons lorsque nous présenterons le fonctionnement du langage d'assemblage.
 
-La deuxième zone, baptisée :term:`segment des données initialisées`, contient l'ensemble des données et chaînes de caractères qui sont utilisées dans le programme. Ce segment contient deux types de données. Tout d'abord, il comprend l'ensemble des variables globales explicitement initialisées par le programme (dans le cas contraire, elles sont initialisées à zéro par le compilateur et appartiennent alors au :term:`segment des données non-initialisées`). Ensuite, les constantes et les chaînes de caractères utilisées par le programme.
+    Le segment des données initialisées
+    -----------------------------------
 
-.. literalinclude:: /C/S3-src/dataseg.c
-   :encoding: utf-8
-   :language: c
-   :start-after: ///AAA
-   :end-before: ///BBB
+    La deuxième zone, baptisée :term:`segment des données initialisées`, contient l'ensemble des données et chaînes de caractères qui sont utilisées dans le programme. Ce segment contient deux types de données. Tout d'abord, il comprend l'ensemble des variables globales explicitement initialisées par le programme (dans le cas contraire, elles sont initialisées à zéro par le compilateur et appartiennent alors au :term:`segment des données non-initialisées`). Ensuite, les constantes et les chaînes de caractères utilisées par le programme.
 
-Dans le programme ci-dessus, la variable ``g_init``, la constante ``un`` et les tableaux ``tab`` et ``cours`` sont dans la zone réservée aux variables initialisées. En pratique, leur valeur d'initialisation sera chargée depuis le fichier exécutable lors de son chargement en mémoire. Il en va de même pour toutes les chaînes de caractères qui sont utilisées comme arguments aux appels à ``printf(3)``.
+    .. literalinclude:: /C/S3-src/dataseg.c
+       :encoding: utf-8
+       :language: c
+       :start-after: ///AAA
+       :end-before: ///BBB
 
-L'exécution de ce programme produit la sortie standard suivante.
+    Dans le programme ci-dessus, la variable ``g_init``, la constante ``un`` et les tableaux ``tab`` et ``cours`` sont dans la zone réservée aux variables initialisées. En pratique, leur valeur d'initialisation sera chargée depuis le fichier exécutable lors de son chargement en mémoire. Il en va de même pour toutes les chaînes de caractères qui sont utilisées comme arguments aux appels à ``printf(3)``.
 
-.. literalinclude:: /C/S3-src/dataseg.out
-   :encoding: utf-8
-   :language: console
+    L'exécution de ce programme produit la sortie standard suivante.
 
+    .. literalinclude:: /C/S3-src/dataseg.out
+       :encoding: utf-8
+       :language: console
 
-Cette sortie illustre bien les adresses où les variables globales sont stockées. La variable globale ``msg`` fait notamment partie du :term:`segment des données non-initialisées`.
 
-Le segment des données non-initialisées
----------------------------------------
+    Cette sortie illustre bien les adresses où les variables globales sont stockées. La variable globale ``msg`` fait notamment partie du :term:`segment des données non-initialisées`.
 
-La troisième zone est le :term:`segment des données non-initialisées`, réservée aux variables non-initialisées. Cette zone mémoire est initialisée à zéro par le système d'exploitation lors du démarrage du programme. Dans l'exemple ci-dessus, c'est dans cette zone que l'on stockera les valeurs de la variable ``g`` et des tableaux ``array`` et ``msg``.
+    Le segment des données non-initialisées
+    ---------------------------------------
 
-.. note:: Initialisation des variables
+    La troisième zone est le :term:`segment des données non-initialisées`, réservée aux variables non-initialisées. Cette zone mémoire est initialisée à zéro par le système d'exploitation lors du démarrage du programme. Dans l'exemple ci-dessus, c'est dans cette zone que l'on stockera les valeurs de la variable ``g`` et des tableaux ``array`` et ``msg``.
 
- Un point important auquel tout programmeur C doit faire attention est l'initialisation correcte de l'ensemble des variables utilisées dans un programme. Le compilateur C est nettement plus permissif qu'un compilateur Java et il autorisera l'utilisation de variables avant qu'elles n'aient été explicitement initialisées, ce qui peut donner lieu à des erreurs parfois très difficiles à corriger.
+    .. note:: Initialisation des variables
 
- En C, par défaut les variables globales qui ne sont pas explicitement initialisées dans un programme sont initialisées à la valeur zéro par le compilateur. Plus précisément, la zone mémoire qui correspond à chaque variable globale non-explicitement initialisée contiendra des bits valant 0. Pour les variables locales, le langage C n'impose aucune initialisation par défaut au compilateur. Par souci de performance et sachant qu'un programmeur ne devrait jamais utiliser de variable locale non explicitement initialisée, le compilateur C n'initialise pas par défaut la valeur de ces variables. Cela peut avoir des conséquences ennuyeuses comme le montre l'exemple ci-dessous.
+     Un point important auquel tout programmeur C doit faire attention est l'initialisation correcte de l'ensemble des variables utilisées dans un programme. Le compilateur C est nettement plus permissif qu'un compilateur Java et il autorisera l'utilisation de variables avant qu'elles n'aient été explicitement initialisées, ce qui peut donner lieu à des erreurs parfois très difficiles à corriger.
 
- .. literalinclude:: /C/S3-src/initvar.c
-    :encoding: utf-8
-    :language: c
-    :start-after: ///AAA
-    :end-before: ///BBB
+     En C, par défaut les variables globales qui ne sont pas explicitement initialisées dans un programme sont initialisées à la valeur zéro par le compilateur. Plus précisément, la zone mémoire qui correspond à chaque variable globale non-explicitement initialisée contiendra des bits valant 0. Pour les variables locales, le langage C n'impose aucune initialisation par défaut au compilateur. Par souci de performance et sachant qu'un programmeur ne devrait jamais utiliser de variable locale non explicitement initialisée, le compilateur C n'initialise pas par défaut la valeur de ces variables. Cela peut avoir des conséquences ennuyeuses comme le montre l'exemple ci-dessous.
 
- Cet extrait de programme contient deux fonctions erronées. La seconde, baptisée ``read(void)`` déclare un tableau local et retourne la somme des éléments de ce tableau sans l'initialiser. En Java, une telle utilisation d'un tableau non-initialisé serait détectée par le compilateur. En C, elle est malheureusement valide (mais fortement découragée évidemment). La première fonction, ``init(void)`` se contente d'initialiser un tableau local mais ne retourne aucun résultat. Cette fonction ne sert a priori à rien puisqu'elle n'a aucun effet sur les variables globales et ne retourne aucun résultat. L'exécution de ces fonctions via le fragment de code ci-dessous donne cependant un résultat interpellant.
+     .. literalinclude:: /C/S3-src/initvar.c
+        :encoding: utf-8
+        :language: c
+        :start-after: ///AAA
+        :end-before: ///BBB
 
- .. literalinclude:: /C/S3-src/initvar.c
-    :encoding: utf-8
-    :language: c
-    :start-after: ///CCC
-    :end-before: ///DDD
+     Cet extrait de programme contient deux fonctions erronées. La seconde, baptisée ``read(void)`` déclare un tableau local et retourne la somme des éléments de ce tableau sans l'initialiser. En Java, une telle utilisation d'un tableau non-initialisé serait détectée par le compilateur. En C, elle est malheureusement valide (mais fortement découragée évidemment). La première fonction, ``init(void)`` se contente d'initialiser un tableau local mais ne retourne aucun résultat. Cette fonction ne sert a priori à rien puisqu'elle n'a aucun effet sur les variables globales et ne retourne aucun résultat. L'exécution de ces fonctions via le fragment de code ci-dessous donne cependant un résultat interpellant.
 
- .. literalinclude:: /C/S3-src/initvar.out
-    :encoding: utf-8
-    :language: console
+     .. literalinclude:: /C/S3-src/initvar.c
+        :encoding: utf-8
+        :language: c
+        :start-after: ///CCC
+        :end-before: ///DDD
+
+     .. literalinclude:: /C/S3-src/initvar.out
+        :encoding: utf-8
+        :language: console
+
+    Les arguments et variables d'environnement
+    ------------------------------------------
+
+    Lorsque le système d'exploitation charge un programme Unix en mémoire, il initialise dans le haut de la mémoire une zone qui contient deux types de variables. Cette zone contient tout d'abord les arguments qui ont été passés via la ligne de commande. Le système d'exploitation met dans ``argc`` le nombre d'arguments et place dans ``char *argv[]`` tous les arguments passés avec dans ``argv[0]`` le nom du programme qui est exécuté.
 
+    Cette zone contient également les variables d'environnement. Ces variables sont généralement relatives à la configuration du système. Leurs valeurs sont définies par l'administrateur système ou l'utilisateur. De nombreuses variables d'environnement sont utilisées dans les systèmes Unix. Elles servent à modifier le comportement de certains programmes. Une liste exhaustive de toutes les variables d'environnement est impossible, mais en voici quelques unes qui sont utiles en pratique [#fenvbash]_:
+
+     - ``HOSTNAME`` : le nom de la machine sur laquelle le programme s'exécute. Ce nom est fixé par l'administrateur système via la commande `hostname(1)`_
+     - ``SHELL`` : l'interpréteur de commande utilisé par défaut pour l'utilisateur courant. Cet interpréteur est lancé par le système au démarrage d'une session de l'utilisateur. Il est stocké dans le fichier des mots de passe et peut être modifié par l'utilisateur via la commande `passwd(1)`_
+     - ``USER`` : le nom de l'utilisateur courant. Sous Unix, chaque utilisateur est identifié par un numéro d'utilisateur et un nom uniques. Ces identifiants sont fixés par l'administrateur système via la commande `passwd(1)`_
+     - ``HOME``: le répertoire d'accueil de l'utilisateur courant. Ce répertoire d'accueil appartient à l'utilisateur. C'est dans ce répertoire qu'il peut stocker tous ses fichiers.
+     - ``PRINTER`` : le nom de l'imprimante par défaut qui est utilisée par la commande `lp(1posix)`_
+     - ``PATH``: cette variable d'environnement contient la liste ordonnée des répertoires que le système parcourt pour trouver un programme à exécuter. Cette liste contient généralement les répertoires dans lesquels le système stocke les exécutables standards, comme ``/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/sbin:`` ainsi que des répertoires relatifs à des programmes spécialisés comme ``/usr/lib/mozart/bin:/opt/python3/bin``. L'utilisateur peut ajouter des répertoires à son ``PATH`` avec `bash(1)`_ en incluant par exemple la commande ``PATH=$PATH:$HOME/local/bin:.`` dans son fichier ``.profile``. Cette commande ajoute au ``PATH`` par défaut le répertoire ``$HOME/local/bin`` et le répertoire courant. Par convention, Unix utilise le caractère ``.`` pour représenter ce répertoire courant.
+
+    La librairie standard contient plusieurs fonctions qui permettent de manipuler les variables d'environnement d'un processus. La fonction `getenv(3)`_ permet de récupérer la valeur associée à une variable d'environnement. La fonction `unsetenv(3)`_ permet de supprimer une variable de l'environnement du programme courant. La fonction `setenv(3)`_ permet elle de modifier la valeur d'une variable d'environnement. Cette fonction alloue de la mémoire pour stocker la nouvelle variable d'environnement et peut échouer si il n'y a pas assez de mémoire disponible pour stocker de nouvelles variables d'environnement. Ces fonctions sont utilisées notamment par l'interpréteur de commande mais parfois par des programmes dont le comportement dépend de la valeur de certaines variables d'environnement. Par exemple, la commande `man(1)`_ utilise différentes variables d'environnement pour déterminer par exemple où les pages de manuel sont stockées et la langue (variable ``LANG``) dans laquelle il faut afficher les pages de manuel.
+
+    Le programme ci-dessous illustre brièvement l'utilisation de `getenv(3)`_, `unsetenv(3)`_ et `setenv(3)`_. Outre ces fonctions, il existe également `clearenv(3)`_ qui permet d'effacer complètement toutes les variables d'environnement du programme courant et `putenv(3)`_ qui était utilisé avant `setenv(3)`_.
+
+    .. literalinclude:: /C/S3-src/argv-env.c
+       :encoding: utf-8
+       :language: c
+       :start-after: ///AAA
+
+La pile (ou stack)
+------------------
+Jusqu'ici, la plupart des données que nous avons manipulé se trouvent dans la :term:`pile` ou :term:`stack` en anglais. C'est une zone très importante car c'est dans cette zone que le processus va stocker l'ensemble des variables locales mais également les valeurs de retour de toutes les fonctions qui sont appelées. Cette zone est gérée comme une pile, d'où son nom. Pour comprendre son fonctionnement, nous utiliserons le programme :download:`/C/S3-src/fact.c` qui permet de calculer une factorielle de façon récursive.
+
+.. literalinclude:: /C/S3-src/fact.c
+  :encoding: utf-8
+  :language: c
+  :start-after: ///BBB
+  :end-before: ///AAA
+
+Lors de l'exécution de la fonction ``compute()``, le programme ci-dessus produit la sortie suivante.
+
+
+.. literalinclude:: /C/S3-src/fact.out
+  :encoding: utf-8
+  :language: console
+  :start-after: ///FACT
 
+Il est intéressant d'analyser en détails ce calcul récursif de la factorielle car il illustre bien le fonctionnement du stack et son utilisation. La variable ``nombre`` est une variable locale qui est allouée lors de l'exécution de la fonction ``compute``, elle se trouve donc sur la pile. Il en va de même des arguments qui sont passés aux fonctions. C'est le cas par exemple de l'argument ``n`` de la fonction ``fact``. Lors de l'exécution de l'appel à ``fact(3)``, la valeur ``3`` est stockée sur la pile pour permettre à la fonction ``fact`` d'y accéder. Ces accès sont relatifs au sommet de la pile comme nous aurons l'occasion de le voir dans la présentation du langage d'assemblage. Le premier appel récursif se fait en calculant la valeur de l'argument (``2``) et en appelant la fonction. L'argument est placé sur la pile, mais à une autre adresse que celle utilisée pour ``fact(3)``. Durant son exécution, la fonction ``fact(2)`` accède à ses variables locales sur la pile sans interférer avec les variables locales de l'exécution de ``fact(3)`` qui attend le résultat de ``fact(2)``. Lorsque ``fact(2)`` fait l'appel récursif, la valeur de son argument (``1``) est placée sur la pile et l'exécution de ``fact(1)`` démarre. Celle-ci a comme environnement d'exécution le sommet de la pile qui contient la valeur ``1`` comme argument et la fonction retourne la valeur ``1`` à l'exécution de ``fact(2)`` qui l'avait lancée. Dès la fin de ``fact(1)``, ``fact(2)`` reprend son exécution où elle avait été interrompue et applique la fonction ``times`` avec ``2`` et ``1`` comme arguments. Ces deux arguments sont placés sur le pile et ``times`` peut y accéder au début de son exécution pour calculer la valeur ``2`` et retourner le résultat à la fonction qui l'a appelé, c'est-à-dire ``fact(2)``. Cette dernière retrouve son environnement d'exécution sur la pile. Elle peut maintenant retourner son résultat à la fonction ``fact(3)`` qui l'avait appelée. Celle-ci va appeler la fonction ``times`` avec ``3`` et ``2`` comme arguments et finira par retourner la valeur ``6``.
+
+.. todo: check adresse retour
+
+La pile joue un rôle essentiel lors de l'exécution de programmes en C puisque toutes les variables locales, y compris celles de la fonction ``main`` y sont stockées. Comme nous le verrons lorsque nous aborderons le langage assembleur, la pile sert aussi à stocker l'adresse de retour des fonctions. C'est ce qui permet à l'exécution de ``fact(2)`` de se poursuivre correctement après avoir récupéré la valeur calculée par l'appel à ``fact(1)``. L'utilisation de la pile pour stocker les variables locales et les arguments de fonctions a une conséquence importante. Lorsqu'une variable est définie comme argument ou localement à une fonction ``f``, elle n'est accessible que durant l'exécution de la fonction ``f``. Avant l'exécution de ``f`` cette variable n'existe pas et si ``f`` appelle la fonction ``g``, la variable définie dans ``f`` n'est plus accessible à partir de la fonction ``g``.
+
+En outre, comme le langage C utilise le passage par valeur, les valeurs des arguments d'une fonction sont copiés sur la pile avant de démarrer l'exécution de cette fonction. Lorsque la fonction prend comme argument un entier, cette copie prend un temps très faible. Par contre, lorsque la fonction prend comme argument une ou plusieurs structures de grand taille, celles-ci doivent être entièrement copiées sur la pile. A titre d'exemple, le programme ci-dessous définit une très grande structure contenant un entier et une zone permettant de stocker un million de caractères. Lors de l'appel à la fonction ``sum``, les structures ``one`` et ``two`` sont entièrement copiées sur la pile. Comme chaque structure occupe plus d'un million d'octets, cela prend plusieurs centaines de microsecondes. Cette copie est nécessaire pour respecter le passage par valeur des structures à la fonction ``sum``. Celle-ci ne peut pas modifier le contenu des structures qui lui sont passées en argument. Par comparaison, lors de l'appel à ``sumptr``, seules les adresses de ces deux structures sont copiées sur la pile. Un appel à ``sumptr`` prend moins d'une microseconde, mais bien entendu la fonction ``sumptr`` a accès via les pointeurs passés en argument à toute la zone de mémoire qui leur est associée.
+
+.. literalinclude:: /C/S3-src/structargs.c
+  :encoding: utf-8
+  :language: c
+  :start-after: ///AAA
+  :end-before: ///BBB
+
+
+..
+   Certaines variantes de Unix et certains compilateurs permettent l'allocation de mémoire sur la pile via la fonction `alloca(3)`_. Contrairement à la mémoire allouée par `malloc(3)`_ qui doit être explicitement libérée en utilisant `free(3)`_, la mémoire allouée par `alloca(3)`_ est libérée automatiquement à la fin de l'exécution de la fonction dans laquelle la mémoire a été allouée. Cette façon d'allouer de la mémoire sur la pile n'est pas portable et il est préférable de n'allouer de la mémoire que sur le tas en utilisant `malloc(3)`_.
+
+   Les versions récentes du C et notamment [C99]_ permettent d'allouer de façon dynamique un tableau sur la pile. Cette fonctionnalité peut être utile dans certains cas, mais elle peut aussi être la source de nombreuses erreurs et difficultés. Pour bien comprendre ce problème, considérons à nouveau la fonction ``duplicate`` qui a été définie précédemment en utilisant `malloc(3)`_  et des pointeurs.
+
+   .. literalinclude:: /C/S3-src/strcpy.c
+      :encoding: utf-8
+      :language: c
+      :start-after: ///AAA
+      :end-before: ///BBB
 
 
 Le tas (ou `heap`)
 ------------------
 
-La quatrième zone de la mémoire est le :term:`tas` (ou :term:`heap` en anglais). Vu l'importance pratique de la terminologie anglaise, c'est celle-ci que nous utiliserons dans le cadre de ce document. C'est une des deux zones dans laquelle un programme peut obtenir de la mémoire supplémentaire pour stocker de l'information. Un programme peut y réserver une zone permettant de stocker des données et y associer un pointeur.
+La deuxième zone de la mémoire que nous voyons dans le cadre de ce cours est le :term:`tas` (ou :term:`heap` en anglais). Vu l'importance pratique de la terminologie anglaise, c'est celle-ci que nous utiliserons dans le cadre de ce document. C'est une des deux zones dans laquelle un programme peut obtenir de la mémoire supplémentaire pour stocker de l'information. Un programme peut y réserver une zone permettant de stocker des données et y associer un pointeur.
 
 Le système d'exploitation mémorise, pour chaque processus en cours d'exécution, la limite supérieure de son :term:`heap`. Le système d'exploitation permet à un processus de modifier la taille de son heap via les appels systèmes `brk(2)`_  et `sbrk(2)`_. Malheureusement, ces deux appels systèmes se contentent de modifier la limite supérieure du :term:`heap` sans fournir une API permettant au processus d'y allouer efficacement des blocs de mémoire. Rares sont les processus qui utilisent directement `brk(2)`_  si ce n'est sous la forme d'un appel à ``sbrk(0)`` de façon à connaître la limite supérieure actuelle du :term:`heap`.
 
@@ -250,6 +318,21 @@ Un autre exemple d'utilisation de `malloc(3)`_ est la fonction ``duplicate`` ci-
    :start-after: ///AAA
    :end-before: ///BBB
 
+
+Un étudiant pourrait vouloir éviter d'utiliser `malloc(3)`_ et écrire plutôt la fonction suivante en définissant directement sa chaine de caractère de retour en variable locale, dans le :term:`stack`.
+
+.. literalinclude:: /C/S3-src/strcpy.c
+   :encoding: utf-8
+   :language: c
+   :start-after: ///BBB
+   :end-before: ///CCC
+
+.. spelling::
+
+ warning
+
+Lors de la compilation, `gcc(1)`_ affiche le :term:`warning` ``In function ‘duplicate2’: warning: function returns address of local variable``. Ce warning indique que la ligne ``return str2;`` retourne l'adresse d'une variable locale qui n'est plus accessible à la fin de la fonction ``duplicate2``. En effet, la zone mémoire allouée sur la pile pour ``str2`` est libérée lors de l'exécution de ``return str2;`` puisque toute mémoire allouée sur la pile est implicitement libérée à la fin de l'exécution de la fonction durant laquelle elle a été allouée. Donc, une fonction qui appelle ``duplicate2`` ne peut pas récupérer les données se trouvant dans la zone mémoire qui a été allouée par ``duplicate2``.
+
 `malloc(3)`_ et `free(3)`_ sont fréquemment utilisés dans des programmes qui manipulent des structures de données dont la taille varie dans le temps. C'est le cas pour les différents sortes de listes chaînées, les piles, les queues, les arbres, ... L'exemple ci-dessous (:download:`/C/S3-src/stack.c`) illustre une implémentation d'une pile simple en C. Le pointeur vers le sommet de la pile est défini comme une variable globale. Chaque élément de la pile est représenté comme un pointeur vers une structure qui contient un pointeur vers la donnée stockée (dans cet exemple des fractions) et l'élément suivant sur la pile. Les fonctions ``push`` et ``pop`` permettent respectivement d'ajouter un élément et de retirer un élément au sommet de la pile. La fonction ``push`` alloue la mémoire nécessaire avec `malloc(3)`_ tandis que la fonction ``pop`` utilise `free(3)`_ pour libérer la mémoire dès qu'un élément est retiré.
 
 
@@ -275,7 +358,7 @@ Lors de son exécution le programme :download:`/C/S3-src/stack.c` présenté ci-
    :language: console
 
 
-Le tas (ou :term:`heap`) joue un rôle très important dans les programmes C. Les données qui sont stockées dans cette zone de la mémoire sont accessibles depuis toute fonction qui possède un pointeur vers la zone correspondante
+Le tas (ou :term:`heap`) joue un rôle très important dans les programmes C. Les données qui sont stockées dans cette zone de la mémoire sont accessibles depuis toute fonction qui possède un pointeur vers la zone correspondante.
 
 
 .. note:: Ne comptez jamais sur les `free(3)`_ implicites
@@ -305,104 +388,18 @@ L'exécution du programme ci-dessus affiche le résultat suivant sur la sortie s
 
 Lors de l'exécution du programme, on remarque que la première zone mémoire retournée par `malloc(3)`_ a été initialisée à zéro. C'est souvent le cas en pratique pour des raisons de sécurité, mais ce serait une erreur de faire cette hypothèse dans un programme. Si la zone de mémoire doit être initialisée, la mémoire doit être allouée par `calloc(3)`_ ou via une initialisation explicite ou en utilisant des fonctions telles que `bzero(3)`_ ou `memset(3)`_.
 
-Les arguments et variables d'environnement
-------------------------------------------
-
-Lorsque le système d'exploitation charge un programme Unix en mémoire, il initialise dans le haut de la mémoire une zone qui contient deux types de variables. Cette zone contient tout d'abord les arguments qui ont été passés via la ligne de commande. Le système d'exploitation met dans ``argc`` le nombre d'arguments et place dans ``char *argv[]`` tous les arguments passés avec dans ``argv[0]`` le nom du programme qui est exécuté.
-
-Cette zone contient également les variables d'environnement. Ces variables sont généralement relatives à la configuration du système. Leurs valeurs sont définies par l'administrateur système ou l'utilisateur. De nombreuses variables d'environnement sont utilisées dans les systèmes Unix. Elles servent à modifier le comportement de certains programmes. Une liste exhaustive de toutes les variables d'environnement est impossible, mais en voici quelques unes qui sont utiles en pratique [#fenvbash]_:
-
- - ``HOSTNAME`` : le nom de la machine sur laquelle le programme s'exécute. Ce nom est fixé par l'administrateur système via la commande `hostname(1)`_
- - ``SHELL`` : l'interpréteur de commande utilisé par défaut pour l'utilisateur courant. Cet interpréteur est lancé par le système au démarrage d'une session de l'utilisateur. Il est stocké dans le fichier des mots de passe et peut être modifié par l'utilisateur via la commande `passwd(1)`_
- - ``USER`` : le nom de l'utilisateur courant. Sous Unix, chaque utilisateur est identifié par un numéro d'utilisateur et un nom uniques. Ces identifiants sont fixés par l'administrateur système via la commande `passwd(1)`_
- - ``HOME``: le répertoire d'accueil de l'utilisateur courant. Ce répertoire d'accueil appartient à l'utilisateur. C'est dans ce répertoire qu'il peut stocker tous ses fichiers.
- - ``PRINTER`` : le nom de l'imprimante par défaut qui est utilisée par la commande `lp(1posix)`_
- - ``PATH``: cette variable d'environnement contient la liste ordonnée des répertoires que le système parcourt pour trouver un programme à exécuter. Cette liste contient généralement les répertoires dans lesquels le système stocke les exécutables standards, comme ``/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/sbin:`` ainsi que des répertoires relatifs à des programmes spécialisés comme ``/usr/lib/mozart/bin:/opt/python3/bin``. L'utilisateur peut ajouter des répertoires à son ``PATH`` avec `bash(1)`_ en incluant par exemple la commande ``PATH=$PATH:$HOME/local/bin:.`` dans son fichier ``.profile``. Cette commande ajoute au ``PATH`` par défaut le répertoire ``$HOME/local/bin`` et le répertoire courant. Par convention, Unix utilise le caractère ``.`` pour représenter ce répertoire courant.
-
-La librairie standard contient plusieurs fonctions qui permettent de manipuler les variables d'environnement d'un processus. La fonction `getenv(3)`_ permet de récupérer la valeur associée à une variable d'environnement. La fonction `unsetenv(3)`_ permet de supprimer une variable de l'environnement du programme courant. La fonction `setenv(3)`_ permet elle de modifier la valeur d'une variable d'environnement. Cette fonction alloue de la mémoire pour stocker la nouvelle variable d'environnement et peut échouer si il n'y a pas assez de mémoire disponible pour stocker de nouvelles variables d'environnement. Ces fonctions sont utilisées notamment par l'interpréteur de commande mais parfois par des programmes dont le comportement dépend de la valeur de certaines variables d'environnement. Par exemple, la commande `man(1)`_ utilise différentes variables d'environnement pour déterminer par exemple où les pages de manuel sont stockées et la langue (variable ``LANG``) dans laquelle il faut afficher les pages de manuel.
-
-Le programme ci-dessous illustre brièvement l'utilisation de `getenv(3)`_, `unsetenv(3)`_ et `setenv(3)`_. Outre ces fonctions, il existe également `clearenv(3)`_ qui permet d'effacer complètement toutes les variables d'environnement du programme courant et `putenv(3)`_ qui était utilisé avant `setenv(3)`_.
-
-.. literalinclude:: /C/S3-src/argv-env.c
-   :encoding: utf-8
-   :language: c
-   :start-after: ///AAA
-
-
-La pile (ou stack)
-------------------
-
-La :term:`pile` ou :term:`stack` en anglais est la dernière zone de mémoire utilisée par un processus. C'est une zone très importante car c'est dans cette zone que le processus va stocker l'ensemble des variables locales mais également les valeurs de retour de toutes les fonctions qui sont appelées. Cette zone est gérée comme une pile, d'où son nom. Pour comprendre son fonctionnement, nous utiliserons le programme :download:`/C/S3-src/fact.c` qui permet de calculer une factorielle de façon récursive.
-
-.. literalinclude:: /C/S3-src/fact.c
-   :encoding: utf-8
-   :language: c
-   :start-after: ///BBB
-   :end-before: ///AAA
-
-Lors de l'exécution de la fonction ``compute()``, le programme ci-dessus produit la sortie suivante.
-
-
-.. literalinclude:: /C/S3-src/fact.out
-   :encoding: utf-8
-   :language: console
-   :start-after: ///FACT
-
-Il est intéressant d'analyser en détails ce calcul récursif de la factorielle car il illustre bien le fonctionnement du stack et son utilisation.
-
-Tout d'abord, il faut noter que les fonctions ``fact`` et ``times`` se trouvent, comme toutes les fonctions définies dans le programme, à l'intérieur du :term:`segment text`. La variable ``nombre`` quant à elle se trouve sur la pile en haut de la mémoire. Il s'agit d'une variable locale qui est allouée lors de l'exécution de la fonction ``compute``. Il en va de même des arguments qui sont passés aux fonctions. Ceux-ci sont également stockés sur la pile. C'est le cas par exemple de l'argument ``n`` de la fonction ``fact``. Lors de l'exécution de l'appel à ``fact(3)``, la valeur ``3`` est stockée sur la pile pour permettre à la fonction ``fact`` d'y accéder. Ces accès sont relatifs au sommet de la pile comme nous aurons l'occasion de le voir dans la présentation du langage d'assemblage. Le premier appel récursif se fait en calculant la valeur de l'argument (``2``) et en appelant la fonction. L'argument est placé sur la pile, mais à une autre adresse que celle utilisée pour ``fact(3)``. Durant son exécution, la fonction ``fact(2)`` accède à ses variables locales sur la pile sans interférer avec les variables locales de l'exécution de ``fact(3)`` qui attend le résultat de ``fact(2)``. Lorsque ``fact(2)`` fait l'appel récursif, la valeur de son argument (``1``) est placée sur la pile et l'exécution de ``fact(1)`` démarre. Celle-ci a comme environnement d'exécution le sommet de la pile qui contient la valeur ``1`` comme argument et la fonction retourne la valeur ``1`` à l'exécution de ``fact(2)`` qui l'avait lancée. Dès la fin de ``fact(1)``, ``fact(2)`` reprend son exécution où elle avait été interrompue et applique la fonction ``times`` avec ``2`` et ``1`` comme arguments. Ces deux arguments sont placés sur le pile et ``times`` peut y accéder au début de son exécution pour calculer la valeur ``2`` et retourner le résultat à la fonction qui l'a appelé, c'est-à-dire ``fact(2)``. Cette dernière retrouve son environnement d'exécution sur la pile. Elle peut maintenant retourner son résultat à la fonction ``fact(3)`` qui l'avait appelée. Celle-ci va appeler la fonction ``times`` avec ``3`` et ``2`` comme arguments et finira par retourner la valeur ``6``.
-
-La pile joue un rôle essentiel lors de l'exécution de programmes en C puisque toutes les variables locales, y compris celles de la fonction ``main`` y sont stockées. Comme nous le verrons lorsque nous aborderons le langage assembleur, la pile sert aussi à stocker l'adresse de retour des fonctions. C'est ce qui permet à l'exécution de ``fact(2)`` de se poursuivre correctement après avoir récupéré la valeur calculée par l'appel à ``fact(1)``. L'utilisation de la pile pour stocker les variables locales et les arguments de fonctions a une conséquence importante. Lorsqu'une variable est définie comme argument ou localement à une fonction ``f``, elle n'est accessible que durant l'exécution de la fonction ``f``. Avant l'exécution de ``f`` cette variable n'existe pas et si ``f`` appelle la fonction ``g``, la variable définie dans ``f`` n'est plus accessible à partir de la fonction ``g``.
-
-En outre, comme le langage C utilise le passage par valeur, les valeurs des arguments d'une fonction sont copiés sur la pile avant de démarrer l'exécution de cette fonction. Lorsque la fonction prend comme argument un entier, cette copie prend un temps très faible. Par contre, lorsque la fonction prend comme argument une ou plusieurs structures de grand taille, celles-ci doivent être entièrement copiées sur la pile. A titre d'exemple, le programme ci-dessous définit une très grande structure contenant un entier et une zone permettant de stocker un million de caractères. Lors de l'appel à la fonction ``sum``, les structures ``one`` et ``two`` sont entièrement copiées sur la pile. Comme chaque structure occupe plus d'un million d'octets, cela prend plusieurs centaines de microsecondes. Cette copie est nécessaire pour respecter le passage par valeur des structures à la fonction ``sum``. Celle-ci ne peut pas modifier le contenu des structures qui lui sont passées en argument. Par comparaison, lors de l'appel à ``sumptr``, seules les adresses de ces deux structures sont copiées sur la pile. Un appel à ``sumptr`` prend moins d'une microseconde, mais bien entendu la fonction ``sumptr`` a accès via les pointeurs passés en argument à toute la zone de mémoire qui leur est associée.
-
-.. literalinclude:: /C/S3-src/structargs.c
-   :encoding: utf-8
-   :language: c
-   :start-after: ///AAA
-   :end-before: ///BBB
-
-
-Certaines variantes de Unix et certains compilateurs permettent l'allocation de mémoire sur la pile via la fonction `alloca(3)`_. Contrairement à la mémoire allouée par `malloc(3)`_ qui doit être explicitement libérée en utilisant `free(3)`_, la mémoire allouée par `alloca(3)`_ est libérée automatiquement à la fin de l'exécution de la fonction dans laquelle la mémoire a été allouée. Cette façon d'allouer de la mémoire sur la pile n'est pas portable et il est préférable de n'allouer de la mémoire que sur le tas en utilisant `malloc(3)`_.
-
-Les versions récentes du C et notamment [C99]_ permettent d'allouer de façon dynamique un tableau sur la pile. Cette fonctionnalité peut être utile dans certains cas, mais elle peut aussi être la source de nombreuses erreurs et difficultés. Pour bien comprendre ce problème, considérons à nouveau la fonction ``duplicate`` qui a été définie précédemment en utilisant `malloc(3)`_  et des pointeurs.
-
-.. literalinclude:: /C/S3-src/strcpy.c
-   :encoding: utf-8
-   :language: c
-   :start-after: ///AAA
-   :end-before: ///BBB
-
-
-Un étudiant pourrait vouloir éviter d'utiliser `malloc(3)`_ et écrire plutôt la fonction suivante.
-
-.. literalinclude:: /C/S3-src/strcpy.c
-   :encoding: utf-8
-   :language: c
-   :start-after: ///BBB
-   :end-before: ///CCC
-
-.. spelling::
-
-   warning
-                
-Lors de la compilation, `gcc(1)`_ affiche le :term:`warning` ``In function ‘duplicate2’: warning: function returns address of local variable``. Ce warning indique que la ligne ``return str2;`` retourne l'adresse d'une variable locale qui n'est plus accessible à la fin de la fonction ``duplicate2``. En effet, l'utilisation de tableaux alloués dynamiquement sur la pile est équivalent à une utilisation implicite de `alloca(3)`_. La déclaration ``char str2[len];`` est équivalente à ``char *str2 =(char *)alloca(len*sizeof(char));`` et la zone mémoire allouée sur la pile pour ``str2`` est libérée lors de l'exécution de ``return str2;`` puisque toute mémoire allouée sur la pile est implicitement libérée à la fin de l'exécution de la fonction durant laquelle elle a été allouée. Donc, une fonction qui appelle ``duplicate2`` ne peut pas récupérer les données se trouvant dans la zone mémoire qui a été allouée par ``duplicate2``.
-
 
 
 .. rubric:: Footnotes
 
 .. [#fpossible] Pour des raisons de performance, le compilateur C ne génère pas de code permettant de vérifier automatiquement qu'un accès via un pointeur pointe vers une zone de mémoire qui est libre. Il est donc parfois possible d'accéder à une zone mémoire qui a été libérée, mais le programme n'a aucune garantie sur la valeur qu'il y trouvera. Ce genre d'accès à des zones mémoires libérées doit bien entendu être complètement proscrit.
 
-.. [#ggetrlimit] Sur de nombreuses variantes de Unix, cette limite à la taille du stack dépend du matériel utilisé et peut être configurée par l'administrateur système. Un processus peut connaître la taille maximale de son stack en utilisant l'appel système `getrlimit(2)`_. L'administrateur système peut modifier ces limites via l'appel système `setrlimit(2)`_. La commande ``ulimit`` de `bash(1)`_ permet également de manipuler ces limites.
+.. .. [#ggetrlimit] Sur de nombreuses variantes de Unix, cette limite à la taille du stack dépend du matériel utilisé et peut être configurée par l'administrateur système. Un processus peut connaître la taille maximale de son stack en utilisant l'appel système `getrlimit(2)`_. L'administrateur système peut modifier ces limites via l'appel système `setrlimit(2)`_. La commande ``ulimit`` de `bash(1)`_ permet également de manipuler ces limites.
 
-.. [#fetext] Dans de nombreuses variantes de Unix, il est possible de connaître le sommet du segment :term:`text` d'un processus grâce à la variable :term:`etext`. Cette variable, de type ``char`` est initialisée par le système au chargement du processus. Elle doit être déclarée comme variable de type ``extern char etext`` et son adresse (``&etext``) correspond au sommet du segment text.
+.. .. [#fetext] Dans de nombreuses variantes de Unix, il est possible de connaître le sommet du segment :term:`text` d'un processus grâce à la variable :term:`etext`. Cette variable, de type ``char`` est initialisée par le système au chargement du processus. Elle doit être déclarée comme variable de type ``extern char etext`` et son adresse (``&etext``) correspond au sommet du segment text.
 
-.. [#fvmem] Nous verrons ultérieurement que grâce à l'utilisation de la mémoire virtuelle, il est possible pour un processus d'utiliser des zones de mémoire qui ne sont pas contiguës.
+.. .. [#fvmem] Nous verrons ultérieurement que grâce à l'utilisation de la mémoire virtuelle, il est possible pour un processus d'utiliser des zones de mémoire qui ne sont pas contiguës.
 
 .. [#fothermalloc] Il existe différentes alternatives à l'utilisation de `malloc(3)`_ pour l'allocation de mémoire comme `Hoard <http://www.hoard.org/>`_ ou `gperftools <http://code.google.com/p/gperftools/>`_
 
-.. [#fenvbash] Il possible de lister les définitions actuelles des variables d'environnement via la commande `printenv(1)`_. Les interpréteurs de commande tels que `bash(1)`_ permettent de facilement modifier les valeurs de ces variables. La plupart d'entre elles sont initialisées par le système ou via les fichiers qui sont chargés automatiquement au démarrage de l'interpréteur comme ``/etc/profile`` qui contient les variables fixées par l'administrateur système ou le fichier ``.profile`` du répertoire d'accueil de l'utilisateur qui contient les variables d'environnement propres à cet utilisateur.
-
-
-
+.. .. [#fenvbash] Il possible de lister les définitions actuelles des variables d'environnement via la commande `printenv(1)`_. Les interpréteurs de commande tels que `bash(1)`_ permettent de facilement modifier les valeurs de ces variables. La plupart d'entre elles sont initialisées par le système ou via les fichiers qui sont chargés automatiquement au démarrage de l'interpréteur comme ``/etc/profile`` qui contient les variables fixées par l'administrateur système ou le fichier ``.profile`` du répertoire d'accueil de l'utilisateur qui contient les variables d'environnement propres à cet utilisateur.
diff --git a/Theorie/glossaire.rst b/Theorie/glossaire.rst
index 577db1113704e9c533f2bdf4c2a8ae5f2bfde0af..b9f0bfe5183ce72faf743fa46695a56fe1b4a53d 100644
--- a/Theorie/glossaire.rst
+++ b/Theorie/glossaire.rst
@@ -409,3 +409,6 @@ Glossaire
 
    raspberry pi
     Systèmes informatiques développés par la Raspberry Pi Foundation, voir https://www.raspberrypi.org
+
+   raspbian
+    Variante de GNU/Linux disponible depuis https://www.raspbian.org
diff --git a/Theorie/intro.rst b/Theorie/intro.rst
index 3abc5b3c78b919f3fddeddf5c4fcd67ce5ccc065..cb570b2bebe072ff1258c2493d1b5361e6961652 100644
--- a/Theorie/intro.rst
+++ b/Theorie/intro.rst
@@ -117,7 +117,7 @@ Unix s'appuie sur la notion de processus. Une application est composée de un ou
 
 Dans le cadre de ce cours, nous aurons l'occasion de voir en détails de nombreuses librairies d'un système Unix et verrons le fonctionnement d'appels systèmes qui permettent aux logiciels d'interagir directement avec le noyau. Le système Unix étant majoritairement écrit en langage C, ce langage est le langage de choix pour de nombreuses applications. Nous le verrons donc en détails.
 
-Pour vous permettre de mettre vos apprentissages en pratique, vous recevrez durant le quadrimestre un raspberry pi. Il est possible d'installer différents systèmes d'exploitation sur celui-ci. Nous utiliserons raspbian  qui est lui aussi une variante de Unix.
+Pour vous permettre de mettre vos apprentissages en pratique, vous recevrez durant le quadrimestre un :term:`raspberry pi`. Il est possible d'installer différents systèmes d'exploitation sur celui-ci. Nous utiliserons :term:`raspbian` qui est une variante de GNU/Linux.
 
 Utilitaires
 ^^^^^^^^^^^