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

Dupliquer possible:
Quoi et où sont la stack et le tas?

En ce qui concerne les concepts de base de la mise en page de la mémoire dans un programme ac, je comprends que:

  • Le langage utilise deux structures de données principales, stack et tas .
  • La stack est créée pour stocker les variables locales et la tenue des livres des sous-routines
  • Heap est créé pour stocker les variables du programme allouées dynamicment
  • Le tas est de longueur variable par nature (pas très sûr sur la stack)
  • Normalement, il est de la responsabilité du compilateur / langage de demander au système d’exploitation de créer ces structures de données avant l’exécution.

Des questions

  • Quelle est la taille initiale avec laquelle une stack / tas est créé? et qui le décide?
  • Dans quelle mémoire physique sont-ils créés? Je vois une description générale comme “La stack est créée dans l’adresse de niveau supérieur et le segment de mémoire dans l’ adresse de niveau inférieur” .

“La stack est créée dans l’adresse de niveau supérieur et le segment de mémoire dans l’adresse de niveau inférieur”

C’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 vie réelle. Mais ce n’est pas littéralement vrai.

C’est assez facile à explorer, cependant:

#include  #include  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 stack est en train de baisser et le tas est en train de monter (comme on peut s’y attendre basé sur le mythe), mais la stack a la plus petite adresse, et ils ne grandissent pas les uns vers les autres (mythe détruit).

Btw, ma fonction de check est récursive, et sur certaines implémentations avec certaines options du compilateur, il est possible que la stack ne se déplace pas du tout. Cela vous dit quelque chose sur la raison pour laquelle la norme n'exige pas que tout cela fonctionne. Si elle le faisait, elle pourrait par inadvertance interdire des optimisations utiles.

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 stack par défaut est de 1 Mo

msdn

Sous Linux, la commande suivante peut afficher la version actuelle.

 ulimit -s or -a 

Sur mon Linux 64 bits, il affiche 8192 Ko.

Chaque programme chargé en mémoire comporte plusieurs segments. En assembleur, vous pouvez indiquer chacun de ceux qui utilisent .data, préfixe .code, etc. (intelx86).

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

La stack peut aussi se développer implicitement, c’est-à-dire que lorsque vous effectuez un autre appel de fonction, un enregistrement d’activation est placé dans la stack, en utilisant davantage de mémoire de stack. C’est pourquoi la récursion infinie entraîne un crash lorsqu’un programme est à court de stack allouée.

Lorsqu’un appel de fonction est renvoyé, cet enregistrement d’activation est supprimé et la stack est réduite.

Au contraire, heap augmente dans la direction opposée et contient toute la mémoire allouée dynamicment.

La raison pour laquelle ces deux segments se développent en sens inverse est de maximiser l’utilisation de leur mémoire combinée. Notez que, comme mentionné dans les commentaires, il ne s’agit pas d’un standard courant, mais la plupart des systèmes d’exploitation l’utilisent.

—— stack commence ———– stack grandit vers le bas

——– Sauf s’ils se croisent, un programme peut être exécuté.

——- tas commence ———— tas grandit

Si votre programme n’utilise pas de tas, votre stack peut également utiliser une mémoire maximale, y compris celle de tas. Si le programme effectue peu d’appels récursifs et utilise des variables locales minimales (c’est-à-dire utilise moins de mémoire pour la stack), 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.

Quelle est la taille initiale avec laquelle une stack / tas est créé? 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 stack à l’adresse de niveau bas”.

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

Vraiment. Le standard de langue n’impose pas la taille minimale de la stack ni ne spécifie l’emplacement de la stack 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 systèmes d’exploitation, différents processeurs, différents compilateurs).

Tout d’abord, le standard C n’impose aucune exigence quant à la manière dont la stack / 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 de stack fixe est allouée à 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, les programmes ont généralement tout l’espace d’adressage virtuel disponible.

Wherein physical memory are they are created?

Ceci est spécifique à la plate-forme. Typiquement, la stack croît et le tas grandit.