Question

Je lisais SIOF d'un livre et lui a donné un exemple:

//file1.cpp
extern int y;
int x=y+1;

//file2.cpp
extern int x;
int y=x+1;  

Mon question est:
Dans le code ci-dessus, les choses vont se passer après?

  1. lors de la compilation file1.cpp, feuilles compilateur y comme il est i.e. n'alloue pas de stockage pour elle.
  2. compilateur Alloue stockage pour x, mais n'initialise pas.
  3. Lors de la compilation file2.cpp, feuilles compilateur x comme il est i.e. n'alloue pas de stockage pour elle.
  4. compilateur Alloue stockage pour y, mais n'initialise pas.
  5. Tout en liant file1.o et file2.o, maintenant file2.o est initialisé en premier lieu, maintenant:
    Est-ce que x obtient la valeur initiale de 0? ou ne soit pas initialisé?
Était-ce utile?

La solution

Les étapes d'initialisation sont données dans 3.6.2 « Initialisation des objets non-locales » de la norme C ++:

Etape 1: x et y sont initialisé à zéro avant toute autre initialisation a lieu.

Etape 2: x ou y est dynamiquement initialisé - dont l'un est non spécifié par la norme. Cette variable sera obtenir le 1 de valeur depuis l'autre variable aura été zéro initialisées.

Étape 3:. L'autre variable sera initialisé dynamiquement, obtenir la valeur 2

Autres conseils

SIOF est très bien un artefact d'exécution, le compilateur et éditeur de liens n'ont pas grand chose à faire. Considérons la fonction atexit (), il enregistre les fonctions à appeler à la sortie du programme. De nombreuses implémentations CRT ont quelque chose de similaire pour l'initialisation du programme, permettent de faire appel de ce atinit ().

Initialiser ces variables globales nécessite l'exécution du code, la valeur ne peut être déterminée par le compilateur. Ainsi, le compilateur génère des extraits de code machine qui exécutent l'expression et affecte la valeur. Ces extraits doivent être exécutés avant séries principales ().

C'est là atinit () entre en jeu. Une mise en œuvre du CRT commun parcourt alors une liste des atinit pointeurs de fonction et d'exécuter les extraits d'initialisation, dans l'ordre. Le problème est l'ordre dans lequel les fonctions sont enregistrées dans la liste atinit (). Alors que atexit () a un ordre LIFO bien défini, et il est déterminé implicitement par l'ordre dans lequel les appels de code atexit (), tel est pas le cas pour les fonctions de atinit. La spécification du langage ne nécessite pas d'ordre, il n'y a rien que vous pourriez faire dans votre code pour spécifier un ordre. SIOF est le résultat.

Une mise en œuvre possible est les pointeurs de fonction compilateur émettant dans une section distincte. L'éditeur de liens les fusionne, en produisant la liste des atinit. Si votre compilateur fait que alors l'ordre d'initialisation sera déterminé par l'ordre dans lequel vous liez les fichiers objet. Regardez le fichier de la carte, vous devriez voir la section atinit si votre compilateur fait cela. Il ne sera pas appelé atinit, mais une sorte de nom avec « init » est probable. Un regard sur le code source CRT qui appelle main () devrait donner un aperçu aussi bien.

Le point entier (et la raison pour laquelle il est appelé un « fiasco ») est qu'il est impossible de dire avec certitude ce que se produira dans un cas comme celui-ci. Essentiellement, vous demandez quelque chose d'impossible (que deux variables chacune étant plus grande que l'autre). Comme ils ne peuvent pas le faire, ce qu'ils vont faire est ouvert à une question - ils pourraient produire 0/1 ou 1/0 ou 1/2 ou 2/1, ou peut-être (meilleur cas), juste une erreur message.

Il dépend compilateur et peut dépendre de l'exécution. Un compilateur peut décider de variables statiques paresseux initialisation lorsque la première variable dans un fichier est accessible, ou en tant que chaque variable est consultée. Sinon, il initialise toutes les variables statiques par fichier au moment du lancement, avec l'ordre généralement en fonction de l'ordre de liaison des fichiers. L'ordre de fichier pourrait changer en fonction des dépendances ou d'autres influences, dépendant du compilateur.

Les variables statiques sont généralement initialisé à zéro à moins qu'ils aient une initialiseur constante. Encore une fois, cela dépend compilateur. Donc, une de ces variables sera probablement nulle lorsque l'autre est initialisé. Cependant, étant donné que les deux ont initializers certains compilateurs pourraient laisser les valeurs non défini.

Je pense que le scénario le plus probable serait:

  1. L'espace est alloué pour les variables, et les deux ont la valeur 0.
  2. Une variable, par exemple x, est initialisé et mis à la valeur 1.
  3. L'autre, par exemple y, est initialisé et mis à la valeur 2.

Vous pouvez toujours courir et voir. Il se pourrait que certains compilateurs généreraient code qui va dans une boucle infinie.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top