Pourquoi les livres disent-ils, "le compilateur alloue de l'espace aux variables en mémoire". N'est-ce pas l'exécutable qui fait ça? Je veux dire, par exemple, si j'écris le programme suivant,
#include <iostream>
using namespace std;
int main()
{
int foo;
return 0;
}
et le compiler, et obtenir un exécutable (que ce soit program.exe), maintenant, si je lance program.exe, ce fichier exécutable commandera lui-même d'allouer de l'espace pour la variable foo. N'est-ce pas? Veuillez expliquer pourquoi les livres continuent de dire "le compilateur fera ceci ... fera cela".
sizeof
question se trouve maintenant à Pourquoi est-ce que sizeof est appelé un opérateur de compilation?Réponses:
Vous avez raison de dire que le compilateur en tant que tel a disparu lorsque votre programme s'exécute réellement. Et s'il s'exécute sur une autre machine, le compilateur n'est même plus disponible.
Je suppose que c'est pour faire une distinction claire entre la mémoire réellement allouée par votre propre code. Le compilateur insérera du code dans votre programme qui fait l'allocation de mémoire (comme en utilisant new, malloc ou des commandes similaires).
Les livres utilisent donc souvent "le compilateur fait ceci ou cela" pour dire que le compilateur a ajouté du code qui n'est pas explicitement mentionné dans vos fichiers de code. Il est vrai que ce n'est pas exactement ce qui se passe. De ce point de vue, beaucoup de choses mentionnées dans les tutoriels seraient erronées mais nécessiteraient des explications plutôt élaborées.
la source
malloc
et. Al.Cela dépend de la variable. L'OS alloue le tas, le programme alloue la pile et le compilateur alloue de l'espace pour les globaux / statiques, c'est-à-dire qu'ils sont intégrés dans l'exe lui-même. Si vous allouez 1 Mo de mémoire globale, la taille de votre exe augmentera d'au moins 1 Mo
la source
int test[256][1024]; int main(){ test[0][0]=2; return 0; }
ce petit programme a 1 Mo alloué, mais ne me génère qu'un fichier objet de 1,4 Ko et un exécutable de 8,4 Ko. Il doit cependant utiliser la quantité de RAM appropriée.int a1=1,a2=2,
... tout le chemin vers ..., a1048576=1048576;
Seulement alors, vous obtiendrez certainement quelque chose de plus grand que 1 Mo je pense.ce que le compilateur fera , c'est prendre votre code et le compiler en code machine. Ce que vous mentionnez est un bon exemple où un compilateur n'a besoin que de traduire.
Par exemple, lorsque vous écrivez
Vous pouvez voir cela comme «je dis au compilateur de [ dans la sortie qu'il génère ] demander que l'ordinateur réserve suffisamment de RAM pour un int que je puisse référencer plus tard. Le compilateur utilisera probablement un identifiant de ressource ou un mécanisme pour suivre foo dans le code machine, vous pouvez utiliser foo dans un fichier texte au lieu d'écrire l'assemblage! Vive !
Vous pouvez donc également examiner cela lorsque le compilateur écrit une lettre ( ou peut-être un roman / une encyclopédie ) à tous les processeurs et périphériques ciblés. La lettre est écrite en signaux binaires qui (généralement) peuvent être traduits vers différents processeurs en changeant la cible. N'importe quelle «lettre» et / ou combo peut envoyer toutes sortes de requêtes et / ou de données - veuillez allouer de l'espace pour cette variable que le programmeur a utilisée.
la source
Dire «le compilateur alloue de la mémoire» peut ne pas être exact dans les faits au sens littéral, mais c'est une métaphore qui est suggestive dans le bon sens.
Ce qui se passe vraiment, c'est que le compilateur crée un programme qui alloue sa propre mémoire. Sauf que ce n'est pas le programme qui alloue la mémoire, mais le système d'exploitation.
Donc, ce qui se passe vraiment, c'est que le compilateur crée un programme qui décrit ses besoins en mémoire et que le système d'exploitation prend cette description et l'utilise pour allouer de la mémoire. Sauf que l'OS est un programme et que les programmes ne font rien, ils décrivent un calcul effectué par le CPU. Sauf que le CPU n'est vraiment qu'un circuit électronique compliqué, pas un petit homonculus anthropomorphisé.
Mais il est logique de considérer les programmes et les compilateurs et les processeurs comme de petites personnes qui vivent à l'intérieur d'un ordinateur, non pas parce qu'ils le sont réellement, mais parce que c'est une métaphore qui convient bien au cerveau humain.
Certaines métaphores fonctionnent bien pour décrire les choses à un niveau d'abstraction, mais ne fonctionnent pas aussi bien à un autre niveau. Si vous pensez au niveau du compilateur, il est logique de décrire l'acte de générer du code qui entraînera l'allocation de mémoire lorsque le programme en cours de compilation est en fait exécuté comme "allocation de mémoire". Il est suffisamment proche pour que lorsque nous réfléchissons au fonctionnement d'un compilateur, nous ayons la bonne idée, et ce n'est pas si long que nous oublions ce que nous faisions. Si nous essayons d'utiliser cette métaphore au niveau du programme compilé en cours d'exécution, c'est trompeur d'une manière étrange, ce que vous avez remarqué.
la source
C'est le compilateur qui décide où stocker une variable - peut être dans la pile ou dans un registre gratuit. Quelle que soit la décision de stockage prise par le compilateur, le code machine correspondant pour accéder à cette variable sera généré et ne pourra pas être modifié lors de l'exécution. En ce sens, le compilateur est en charge d'allouer de l'espace aux variables et le programme final.exe agit simplement à l'aveuglette comme un zombie au moment de l'exécution.
Maintenant, ne confondez pas cela avec une gestion de mémoire dynamique différente comme malloc, new ou peut être votre propre gestion de mémoire. Les compilateurs traitent du stockage et de l'accès variables, mais peu importe ce que signifie une valeur réelle dans un autre framework / bibliothèque. Par exemple:
Au moment de l'exécution, malloc peut renvoyer un nombre arbitraire, mais le compilateur s'en fiche, tout ce qui lui importe, c'est où stocker ce numéro.
la source
Une formulation plus précise serait: - "le compilateur dit au chargeur de réserver de l'espace pour les variables"
Dans un environnement C-ish, il y aura trois types d'espace pour les variables: -
Sur un système d'exploitation moderne, la mémoire du tas ne sera pas réellement réservée mais allouée selon les besoins.
la source
Oui, vous avez raison, dans ce cas (en déclarant une variable dans une fonction), la phrase de votre livre est probablement incorrecte: lorsque vous déclarez une variable dans une fonction, elle est allouée sur la pile lors de l'entrée dans la fonction. Quoi qu'il en soit, un compilateur devrait optimiser la situation: si la fonction est non récursive (
main()
est un bon candidat pour elle), il est OK de "l'allouer" au moment de la compilation (sur le BSS).(Si vous êtes curieux de savoir où résident vos variables, vous pouvez le vérifier de manière sale (si vous ne voulez pas examiner la structure du fichier obj, de toute façon, pourquoi pas?), Vous pouvez donc déclarer différents types de variables: constantes, statiques, dynamiques,
malloc()
allouées, etc. et afficher leurs adresses (utilisez le%X
formateurprintf()
pour une meilleure lisibilité). Les variables résidant sur la pile auront des adresses mémoire très différentes.)la source
La seule chose à faire au moment de l'exécution sera de déplacer le pointeur de pile d'un certain montant. Le compilateur décide donc à l'avance:
Celui-ci peut être appelé "allocation", mais bien sûr, pendant la compilation, il ne prend place que dans le modèle que le compilateur a du programme en cours d'exécution.
la source