11
votes

Pourquoi les livres disent-ils: "Le compilateur alloue de l'espace pour les variables en mémoire"?

Pourquoi les livres disent-ils: "Le compilateur alloue de l'espace pour les variables en mémoire". N'est-ce pas l'exécutable qui fait cela? Je veux dire, par exemple, si j'écris le programme suivant,

#include <iostream>
using namespace std;

int main()
{
   int foo = 0;
   cout<<foo;
   return 0;
}


3 commentaires

C'est un mauvais exemple. FOO n'est pas utilisé et sera éliminé pendant la compilation.


@Abyx Man, essayez de comprendre ma question. L'accent n'est pas mis sur si le Var est utilisé. Quoi qu'il en soit, j'ai édité le programme pour vous.


Homme, rien n'a changé avec cette modification. =)


7 Réponses :


3
votes

Il indique que le compilateur alloue de l'espace pour des variables en mémoire, car vous devez également allouer (et libre!) Memory vous-même avec Nouveau / MALLOC ETC.


1 commentaires

Et ce ne sera pas compilateur alors? Vous allez juste l'écrire sur un morceau de papier? ; p



7
votes

C'est juste une utilisation en vrac de terminologie. Bien sûr, le compilateur n'alloue pas la mémoire du programme. Une description plus précise est qu'elle indique à l'exécution combien de mémoire allouer lorsque le programme est en cours d'exécution.

Jusqu'à ce que le programme soit réellement exécuté, ce n'est pas en mémoire (à moins que cela ne soit chargé de manière dynamique, mais même cela se produise pendant la période d'exécution, donc hors de la portée du compilateur), il n'y a donc pas de mémoire à parler. < / p>

Qu'est-ce que ces livres parlent d'allouer des variables dont la taille est connue au moment de la compilation, par opposition à une allocation dynamique Cin >> x; int * y = nouveau [x]; , où la taille n'est pas connue.


0 commentaires

11
votes

Techniquement, l'acte de créer l'espace lui-même est effectué au moment de l'exécution, mais le compilateur est celui de déterminer combien d'espace pour réserver em> sur la pile dans votre cas, pour votre FOO code> variable.

Le compilateur connaît la taille du type int code> et peut donc générer l'instruction d'assembleur de droite qui réserver suffisamment d'espace sur la pile afin de laisser foo code> en direct. p>

Si vous regardez l'assembleur généré ci-dessous (en utilisant MSVC2012) pour le programme que vous avez montré, j'ai commenté certains d'entre eux pour vous montrer ce qui se passe: P>

#include "stdafx.h"
#include <iostream>
using namespace std;

int main()
{
//Setup stack frame for main by storing the stack pointer from the calling function and 
//reserving space for local variables and storing commonly used registers on the stack
002E4390  push        ebp  
002E4391  mov         ebp,esp  
// reserve space for local variables, which is 204 bytes here, no idea why so much.
// this is where the compiler calculated the size of your foo and added that to whatever else needs to be stored on the stack. Subtract from stack pointer (esp) because stack grows downward.  
002E4393  sub         esp,0CCh  
002E4399  push        ebx  
002E439A  push        esi  
002E439B  push        edi  
002E439C  lea         edi,[ebp-0CCh]  // load effective address of [ebp-0CCh], which I suspect would be your foo variable into edi register
002E43A2  mov         ecx,33h  
002E43A7  mov         eax,0CCCCCCCCh  
002E43AC  rep stos    dword ptr es:[edi]  //fill block of memory at es:[edi] with stuff  
   int foo;
   return 0;
002E43AE  xor         eax,eax  //set eax to zero for return value
}
// restore everything back to how it was before main was called
    002E43B0  pop         edi  
    002E43B1  pop         esi  
    002E43B2  pop         ebx  
    002E43B3  mov         esp,ebp  
    002E43B5  pop         ebp  
    002E43B6  ret  


8 commentaires

Une question intéressante ici est la raison pour laquelle le compilateur alloue 204 octets pour les variables locales, lorsque tout ce dont il a besoin est 4. (Vous avez utilisé VC ++ ici, mais j'ai remarqué plusieurs compilateurs qui semblent allouer beaucoup plus que nécessaire.)


@Jameskanze, je me suis demandé ça. Je ne suis pas sûr de savoir pourquoi il semble allouer beaucoup.


@Jameskanze j'ai posé une question demandant ceci: Stackoverflow.com/questions/15806673/... parce que je suis curieux de savoir pourquoi cela serait. Je t'ai mentionné


@Tony the Lion merci à l'homme, votre réponse montre des efforts. Eh bien, je voulais juste vous demander, comment comprenez-vous ces instructions d'assembleur? Faut-il la connaissance de la langue d'assemblage? Si oui, veuillez me suggérer un bon livre pour apprendre la langue de montage depuis le début. Merci encore!


@Rage Oui, j'ai passé du temps dans le passé apprenant l'assembleur de base. L'art de l'assemblage est un bon livre.


@ABYX Je pense que pour montrer ce qui se passe dans ce cas, ce n'est pas vraiment important.


@Tonythelion La sortie de montage que vous avez fournie n'a rien à voir avec le code source. {int foo; Retour 0;} doit être compilé sous forme renvoyer 0; , sans variables locales. Il vient de arriver que votre compilateur a injecté beaucoup d'autres instructions.


@Abyx il vous manque le point. Complètement. L'idée était de décrire à l'OP comment le compilateur génère l'assemblage qui décrit les exigences de la mémoire d'un programme donné. Pas le spécifique, ni pour décrire les possibilités d'optimisation et les approches.



20
votes

Lorsque nous embauchons un architecte pour concevoir une maison, il définit la taille des chambres, etc. et informe les travailleurs (ouvriers) à ce sujet. Les ouvriers font le travail en conséquence. Mais nous dirions toujours " l'architecte a fait la maison de cette façon " et pas " l'ouvrier a fait la maison de cette façon ".

L'ouvrier n'effectue que les étapes définies par l'architecte. Le compilateur effectue en réalité tout le travail de vérification et de définition de la quantité de mémoire à attribuer, etc. au moment de l'exécution, puis ces instructions sont simplement suivies.


0 commentaires

1
votes

Compilateur de cours ne "allège pas d'espace pour les variables". Compilateur génère un code qui attribue l'espace pour les variables en mémoire.

I.e. Si vous avez xxx

dans le code source, le compilateur peut générer un code comme xxx

dans l'architecture x86, généralement que allouer chose sera une seule instruction d'assemblage: xxx

Si vous avez plus d'une variable locale, le compilateur les emballera dans une structure et les allouera Ensemble: xxx

sera compilé comme xxx

ou xxx < / p>


0 commentaires

-1
votes

Vous suggère de lire la construction du compilateur. Concentrez-vous sur la phase de stockage, votre requête serait résolue.

Une fois que le programme est compilé son converti en code d'objet, qui est un code de langue d'assemblage. Chaque ligne d'un programme de langue de haut niveau se traduit par de nombreuses étapes de la langue d'assemblage. Le programme traduit est mis dans l'assembleur qui est exécuté. Il existe une phase d'affectation de stockage dans la construction de Comiler qui se traduit par la table de fonctionnement de la machine (instructions MOT au niveau de montage). C'est là que la répartition spatiale pour les variables / registres est terminée. Il existe un mot-clé de modificateur de registre en C ++.


4 commentaires

Cela ne fournit pas de réponse à la question. Pour critiquer ou demander des éclaircissements d'un auteur, laissez un commentaire sous leur poste - vous pouvez toujours commenter vos propres messages, et une fois que vous avez suffisamment Réputation Vous pourrez Commentaire sur n'importe quel message .


Une fois que le programme est compilé son converti en code d'objet, qui est un code de langue d'assemblage. Chaque ligne d'un programme de langue de haut niveau se traduit par de nombreuses étapes de la langue d'assemblage. Le programme traduit est mis dans l'assembleur qui est exécuté. Il existe une phase d'affectation de stockage dans la construction de Comiler qui se traduit par la table de fonctionnement de la machine (instructions MOT au niveau de montage). C'est là que la répartition spatiale pour les variables / registres est terminée. Il existe un mot-clé de modificateur de registre en C ++.


Je connais Nico O .. Veuillez demander de clarté dans les commentaires des utilisateurs si vous ne comprenez pas la réponse / la perspective des autres. Une fois que l'auteur est conscient du processus de construction du compilateur, il comprendra c'est son code d'objet qui fonctionne. COMPILER est un simple générateur de code vers le niveau de code de programmation inférieur.


-1. Ce que vous dites n'a rien à voir avec la question. Cela s'applique aussi aux commentaires.



0
votes

Le compilateur génère des instructions sur la machine et fonctionne de l'adressage de la mémoire Variables locales occupera. Chaque variable locale reçoit une adresse relative au sommet de la pile, par exemple foo serait supposé être à l'adresse de la mémoire stack_pointer . Si vous aviez une variable FOO2 , il serait placé à l'adresse stack_pointer + 4 où 4 est la taille d'un int .

Lorsque la variable locale FOO est accessible, le compilateur substituera l'adresse détenue dans stack_packer . Le matériel dispose d'un enregistrement spécial stack_pointer qui pointe toujours vers le haut de la pile en cours.

Le compilateur sait quelle taille chaque variable est qu'elle est responsable de la recherche sur struct ou des déclarations et de savoir comment il est aménagé en mémoire. Donc, Tailleof est connu au moment de la compilation et est traité comme une expression constante. Les types primitifs tels que int sont connus d'une certaine taille, par exemple Tailleof (int) est 4.


0 commentaires