2010-12-13 3 views
2

Cela me tracasse depuis longtemps maintenant: Disons que j'ai une fonction:C++: Déclarations de variables de fonction, comment ça fonctionne en interne?

void test(){ 
    int t1, t2, t3; 
    int t4 = 0; 
    int bigvar[10000]; 
    // do something 
} 

Comment l'ordinateur gérer les allocations de mémoire pour les variables?

J'ai toujours pensé que l'espace des variables est sauvegardé dans le fichier .exe que l'ordinateur lira alors, est-ce correct? Mais pour autant que je sache, le tableau bigvar ne prend pas 10000 éléments d'espace int dans le fichier .exe, car il n'est pas initialisé. Alors, comment fonctionne son allocation de mémoire quand j'appelle la fonction?

+0

L'exe est stocké dans un _disk_, et le code compilé y est stocké. Mais quand il est exécuté, il prend la mémoire de l'unité _processor_. Les octets du disque ne correspondent pas aux octets requis pour les variables. –

+0

http://stackoverflow.com/questions/556714/how-does-the-stack-work-in-assembly-language – karlphillip

Répondre

9

Les variables locales comme celles-ci sont généralement implémentées en utilisant le stack du processeur. Cela signifie que la seule chose que le compilateur doit faire est de calculer la taille de chaque variable et de les ajouter ensemble. La somme totale est la quantité à modifier avec le pointeur de pile à l'entrée de la fonction, et à revenir en arrière à la sortie. Chaque variable est ensuite accédée avec son décalage relatif dans ce bloc de mémoire sur la pile.

Votre code, lorsqu'il est compilé sous Linux, finit par ressembler à ceci en assembleur x86:

test: 
     pushl %ebp 
     movl %esp, %ebp 
     subl $40016, %esp 
     movl $0, -4(%ebp) 
     leave 
     ret 

Dans ce qui précède, la constante 40016 $ est l'espace nécessaire pour les quatre ints 32 bits t1, t2, t3 et t4, tandis que les 40000 octets restants représentent le tableau de 10000 éléments bigvar.

+0

bonne explication! – Nawaz

0

Je ne peux pas ajouter beaucoup à ce qui a déjà été dit, à l'exception de quelques notes. Vous pouvez réellement mettre des variables locales dans un fichier exécutable et les avoir allouées dans le segment de données (et initialisées) au lieu du segment de pile. Pour ce faire, déclarez-les comme static. Mais alors toutes les invocations de la fonction partageraient les mêmes variables alors qu'en pile chaque invocation crée un nouvel ensemble de variables. Cela peut causer beaucoup de problèmes lorsque la fonction est appelée simultanément par plusieurs threads ou quand il y a une récursion (essayez d'imaginer ça). C'est pourquoi la plupart des langages utilisent la pile pour les variables locales et static est rarement utilisé.

0

Sur certains anciens compilateurs, j'ai rencontré le comportement que le tableau est alloué statiquement. Ce qui signifie qu'il met de côté la mémoire pour cela quand il charge le programme, et utilise cet espace après cela. Ce comportement n'est pas sûr (voir la réponse de Sergey), et je ne m'attends pas à ce qu'il soit autorisé selon les normes, mais je l'ai rencontré dans la nature. (Je ne me souviens pas de quel compilateur il s'agissait.)

Pour la plupart, les variables locales sont conservées dans la pile, avec les adresses de retour et toutes les autres choses. Cela signifie que les valeurs non initialisées peuvent contenir des informations sensibles. Cela inclut également les tableaux, selon la réponse de unwind.

Une autre implémentation valide est que la variable trouvée sur la pile est un pointeur, et que le compilateur effectue l'allocation et la désallocation (vraisemblablement de manière exceptionnellement sûre) sous le capot. Cela économisera l'espace de pile (qui doit être alloué avant le démarrage du programme, et ne peut pas être facilement étendu pour les architectures x86) et est également très utile pour le standard VLA (tableau de longueur variable, md std :: vector)

Questions connexes