10
votes

Comment la paresseuse peut-elle être une initialisation globale?

Je suis habitué à penser à toute initialisation des globaux / classes statiques comme se déroulant avant la première ligne de principale (). Mais j'ai récemment lu quelque part que la norme permet à l'initialisation de se produire plus tard pour "aider avec le chargement dynamique de modules". Je pouvais voir que cela étant vrai lorsque la liaison dynamique: je ne m'attendrais pas à ce qu'un global initialisé dans une bibliothèque soit initialisé avant de dlopen'ed la bibliothèque. Toutefois, dans le cadre d'un groupe d'unités de traduction reliées statilement liées (fichiers directs de mon application), je trouverais ce comportement très non intuitif. Cela n'arrive-t-il que paresseusement lorsqu'il s'agit d'une liaison dynamique ou peut-être à tout moment? (ou était ce que je lisais juste mal ?;)


0 commentaires

4 Réponses :


0
votes

examinons un pseudocode:

en DLL: xxx

dans application: xxx

SO selon Initialisation statique Appvar2 Obtient 1 + 2 = 3

Initialisation paresseuse applicable pour les variables statiques locales (quelle que soit la DLL) xxx


0 commentaires

6
votes

La norme est la suivante dans 3.6.2 / 3:

Il est défini par la mise en œuvre, qu'il s'agisse d'une initialisation dynamique (8,5, 9,4, 12,1, 12.6.1) d'un objet de La portée des espaces de noms est effectuée avant la première déclaration principale. Si l'initialisation est différée à un point A temps après la première déclaration principale, elle se produira avant la première utilisation de toute fonction ou objet définie. dans la même unité de traduction que l'objet à initialiser.

mais o bien sûr, vous pouvez jamais officiellement dire lorsque l'initialisation a lieu lorsque l'initialisation se produira avant d'accéder à la variable! < / s> comme suit: xxx

i peut être conforme à G ++ 4.2.4 au moins semble exécuter l'initialisation de "I2" avant la principale. >


7 commentaires

En fait, vous pouvez dire. Considérons deux unités de traduction: A et B. Un initialiseur en B incrémente un global dans un (initialisé à 0). Main () imprime simplement la valeur du global dans A. sera-t-il 0 ou 1?


La portée des espaces de noms est-elle distincte de la portée mondiale? Si je prends les globaux de tous les espaces de noms, il est défini dans la norme plutôt que la mise en œuvre définie?


@Joseph: Non, la portée globale est une portée de l'espace de noms ultérieure. Lorsque la norme indique "Portée d'espace de noms", cela signifie "non automaticique ni statique locale", cela ne signifie pas "Vous avez écrit namepace bla {} autour de lui".


De plus, si l'initialisation se produit paresseusement, le compilateur doit générer du code qui vérifie s'il est initialisé et exécutez l'initialisation. Cela peut blesser des ravages lorsqu'il y a plusieurs threads - ce code doit être le fil de sécurité et C ++ ne sanctionne pas officiellement les threads - et lorsqu'il est fait le fil sûr, cette vérification en toute sécurité et une éventuelle initialisation peut être plus coûteuse que prévu.


La portée des espaces de noms est fondamentalement tout ce qui n'est pas en fonction de la fonction ou de la classe. Qu'il soit défini dans l'espace de noms global ou dans un espace de noms défini par l'utilisateur sous cela n'a pas d'importance.


Voici mon animal de compagnie à propos de "Scope global": Stackoverflow.com/Questtions/423823/... . Quoi qu'il en soit, je pense que tu voulais écrire "I2", pas "B" dans la dernière phrase :)


J'ai récemment envoyé un rapport de numéro sur ce paragraphe, aussi: . google.com/group/comp.std.comp ++/browse_thread/thread/...



1
votes

Le problème que l'on voulait résoudre avec cette règle est celui du chargement dynamique. L'indemnité n'est pas limitée au chargement dynamique et pouvait officiellement arriver pour d'autres cas. Je ne connais pas une mise en œuvre qui l'utilise pour autre chose que le chargement dynamique.


0 commentaires

0
votes

Je pense que c'est ce qui s'est passé dans mon cas avec G ++ 4.7 et CMAKE (pas sûr s'il s'agit d'un détail pertinent concernant la cmake). J'ai un code qui enregistre une fonction dans l'usine. Il repose sur le constructeur appelant à partir d'une variable initialisée globalement.

Lorsque ce code était dans la bibliothèque statiquement liée l'initialisation n'a pas eu lieu! Cela fonctionne maintenant bien lorsque je l'ai déplacé dans les fichiers d'objets qui sont liés directement (c'est-à-dire qu'ils ne sont pas combinés dans une bibliothèque d'abord).

Alors, je soupçonne que vous êtes correct.


0 commentaires