web-dev-qa-db-fra.com

Taille de la pile et de la mémoire de tas

Duplicata possible:
Que sont et où sont la pile et le tas?

En ce qui concerne les concepts de base de la disposition de la mémoire dans un programme c, je comprends que:

  • Le langage utilise deux structures de données primaires pile et tas .
  • La pile est créée pour stocker les variables locales et les données de tenue de livres des sous-programmes
  • Le tas est créé pour stocker les variables allouées dynamiquement du programme
  • Le tas est de nature variable (pas très sûr sur la pile)
  • Normalement, il est de la responsabilité du compilateur/langage de demander à l'OS de créer ces structures de données avant l'exécution.

Des questions

  • Quelle est la taille initiale avec laquelle une pile/tas est créée? et qui le décide?
  • Dans quelle mémoire physique sont-ils créés? Je vois une description générale comme "La pile est créée dans l'adresse de niveau supérieur et le tas à l'adresse de bas niveau" Veuillez expliquer ceci
42
Vivek Maran

"La pile est créée dans l'adresse de niveau supérieur et le tas dans l'adresse de bas niveau" Veuillez expliquer ceci

Ceci est un mythe. Il peut avoir une base dans la vérité historique. Cela peut parfois résonner avec des choses que vous voyez dans la vraie vie. Mais ce n'est pas littéralement vrai.

C'est assez facile à explorer, cependant:

#include <stdlib.h>
#include <stdio.h>

void check(int depth) {
    char c;
    char *ptr = malloc(1);
    printf("stack at %p, heap at %p\n", &c, ptr);
    if (depth <= 0) return;
    check(depth-1);
}

int main() {
    check(10);
    return 0;
}

Sur ma machine, je vois:

stack at 0x22ac3b, heap at 0x20010240
stack at 0x22ac0b, heap at 0x200485b0
stack at 0x22abdb, heap at 0x200485c0
stack at 0x22abab, heap at 0x200485d0
stack at 0x22ab7b, heap at 0x200485e0
stack at 0x22ab4b, heap at 0x200485f0
stack at 0x22ab1b, heap at 0x20048600
stack at 0x22aaeb, heap at 0x20048610
stack at 0x22aabb, heap at 0x20048620
stack at 0x22aa8b, heap at 0x20048630
stack at 0x22aa5b, heap at 0x20048640

Ainsi, la pile va vers le bas et le tas monte (comme vous pouvez vous y attendre d'après le mythe), mais la pile a la plus petite adresse, et ils ne se développent pas l'un vers l'autre (mythe éclaté).

Btw, ma fonction check est récursive et, sur certaines implémentations avec certaines options de compilation, vous pouvez voir la pile ne bouger pas du tout. Ce qui vous explique pourquoi la norme n'impose pas comment tout cela fonctionne - si elle le faisait, elle pourrait par inadvertance interdire des optimisations utiles.

58
Steve Jessop

Comme mentionné précédemment, les tailles sont spécifiques au système d'exploitation. Par exemple sur les fenêtres utilisant Visual Studio, la taille de pile par défaut est de 1 Mo

msdn

Sous Linux, la commande suivante peut montrer afficher votre commande actuelle.

ulimit -s or -a

Sur mon Linux mint 64 bits, il affiche 8192 Ko.

Chaque programme, lorsqu'il est chargé en mémoire, comporte plusieurs segments. Dans Assembly, on peut indiquer chacun de ceux qui utilisent le préfixe .data, .code etc. (intelx86).

C'est un segment de données qui comporte plusieurs sous-sections. La pile et le tas en font partie en plus de plusieurs autres.

La pile peut également croître implicitement, c'est-à-dire que lorsque vous effectuez un autre appel de fonction, un enregistrement d'activation est poussé vers la pile, en utilisant plus de mémoire de la pile. C'est pourquoi la récursion infinie entraîne un crash lorsqu'un programme manque de pile allouée.

Lorsqu'un appel de fonction revient, cet enregistrement d'activation est extrait et la pile se réduit.

En revanche, le tas croît dans la direction opposée et contient toute la mémoire allouée dynamiquement.

La raison pour laquelle ces deux segments croissent dans des directions opposées est de maximiser l'utilisation de leur mémoire combinée. Notez que comme mentionné dans les commentaires, ce n'est pas une norme c, mais la plupart des systèmes d'exploitation courants l'ont implémenté.

------ la pile commence ----------- la pile croît vers le bas

-------- À moins qu'ils ne se croisent, un programme peut être exécuté correctement.

------- le tas commence ------------ le tas grandit vers le haut

Si votre programme n'utilise aucun segment, votre pile peut utiliser la mémoire maximale, y compris celle du segment. Si le programme effectue peu d'appels récursifs et utilise un minimum de variables locales (c'est-à-dire utilise moins de mémoire pour la pile), il peut utiliser le tas au maximum.

Les autres parties du segment de données sont BSS, etc., qui peuvent contenir des champs tels que des variables statiques non initialisées

12
fayyazkl

Quelle est la taille initiale avec laquelle une pile/tas est créée? et qui le décide?

Ceci est spécifique au compilateur et au système d'exploitation.

Dans quelle mémoire physique sont-ils créés? Je vois une description générale comme "Le tas est créé dans l'adresse de niveau supérieur et la pile à l'adresse de bas niveau".

Ceci est spécifique au compilateur et au système d'exploitation.

Vraiment. La norme de langue ne prescrit pas la taille de pile minimale ni ne spécifie l'emplacement de la pile ou du tas en mémoire. Et la raison en est que les programmes C sont moins dépendants de ces détails et donc plus portables sur différentes plates-formes (lire: différents OS, différents CPU, différents compilateurs).

8
Alexey Frunze

Tout d'abord, la norme C n'impose aucune exigence sur la façon dont la pile/tas est implémentée par la plate-forme.

What is the initial size with which a stack/heap is created? and who decides it?

Généralement, une taille fixe de pile est allouée pour chaque processus par le système d'exploitation qui est spécifique à la plate-forme. Il n'y a pas de limite sur la taille du tas, le programme a généralement tout l'espace d'adressage virtuel disponible.

Wherein physical memory are they are created?

Ceci est spécifique à la plateforme. Généralement, la pile croît vers le bas et le tas augmente vers le haut.

3
P.P.