GoldenCrystalLe 29/04/2010 à 22:34
La pile c'est la mémoire nécéssaire au fonctionnement même du programme. Typiquement si tous tes registres sont pris (ou même, si tu n'as pas de registres), tu sais (sous réserve qu'il soit pas déjà tout bouffé) que tu as de l'espace de stockage, utilisable pour tes calculs et résultats intermédiaires (donc variables locales et appels de fonctions).
Tu ne peux pas te passer de la pile, mais elle a un emplacement en mémoire fixe, une taille quasiment fixe*, et tu ne contrôles pas directement† son utilisation. En bref, c'est de la mémoire temporaire, dont l'usage doit être très bref et très réduit. Pas vraiment de la « mémoire » dans le sens auquel on penserait au premier abord en fait.
Le tas en revanche, c'est un espace mémoire de taille variable (limité seulement par l'espace d'adressage), non nécéssairement contigu (il peut y avoir des trous dedans, si je ne dis pas de betises), et qui n'est pas strictement nécéssaire au fonctionnement d'un programme (même si ça te limite énormément dans tes possibilités dans ce cas).
Allouer de la mémoire sur la pile est instantané, car la mémoire est déjà alloué, tu ne fais que la « réserver »: « J'ai mis 50 octets là, donc le pointeur de pile en est à x + 50 ». Et comme la taille est fixe, tu peux potentiellement déborder en dehors de la zone autorisée (c'est le débordement de pile, aka stack overflow)
Allouer de la mémoire sur le tas nécéssite de rechercher un emplacement mémoire disponible, de demander de la mémoire à l'OS si il n'y en a plus, et de réserver cet emplacement mémoire (en le marquant occupé de manière adéquate). C'est donc moins rapide niveau performance, surtout si tes objets ne font que quelques octets et/ou ont une durée de vie très courte. (La façon dont c'est implémenté en interne importe peu pour toi ensuite, ça fera juste varier les performances)
En gros, ce que tu alloues dans le tas est alloué de manière dynamique, pour une durée indéterminée (c'est toi qui la détermine, le cas échéant), et ce que tu alloues dans la pile est alloué de manière temporaire (voué à être détruit le plus tôt possible, dans l'ordre exact de création (moyennant magouilles du compilateur))
* tu peux la choisir à la création du thread, c'est 1 Mo par défaut sous Windows il me semble
† autant dire pas du tout, même si ce n'est pas entièrement vrai (typiquement tu sais qu'une récursion infinie va inévitablement bouffer toute la pile‡)
‡ sauf en cas d'optimisation tail-call quand c'est possible, ou quand le compilateur convertit la fonction récursive en fonction linéaire.