Question

Je suis habitué à penser à toute initialisation / GLOBALS statiques classe-membres qui se passe avant la première ligne principale (). Mais je l'ai lu récemment quelque part que la norme permet l'initialisation se produise plus tard « aider avec le chargement dynamique des modules. » Je pouvais voir ce qui est vrai lorsque la liaison dynamique: je n'attendre à une initialisation globale dans une bibliothèque à initialiser avant dlopen'ed la bibliothèque. Cependant, au sein d'un groupe d'unités de traduction liés statiquement ensemble (fichiers .o directs de mon application) je trouverais ce comportement très unintuitive. Est-ce que cela ne se produit paresseusement lors de la liaison ou peut-il se produire dynamiquement à tout moment? (Ou était-ce que je viens de lire mal;)

Était-ce utile?

La solution

La norme est la suivante dans 3.6.2 / 3:

  

Il est défini par l'implémentation si l'initialisation dynamique ou pas (8.5, 9.4, 12.1, 12.6.1) d'un objet de   champ d'espace de noms est effectué avant la première déclaration de la principale. Si l'initialisation est reporté à un moment donné   dans le temps après la première déclaration de la principale, il se produire avant la première utilisation d'une fonction ou d'un objet défini   dans la même unité de traduction en tant que l'objet à être initialisé.

Mais o Bien sûr, vous pouvez jamais officiellement dire lorsque l'initialisation a lieu depuis l'initialisation se produira avant d'accéder à la variable! comme suit:

// t1.cc
#include <iostream>
int i1 = 0;

int main () {
  std::cout << i1 << std::endl

// t2.cc
extern int i1;
int i2 = ++i1;

Je peux conformer que g ++ 4.2.4 au moins semble effectuer l'initialisation de « i2 » avant principal.

Autres conseils

Le problème que l'on voulait résoudre avec cette règle est celle de chargement dynamique. L'allocation ne se limite pas à une charge dynamique et pourrait officiellement se produire pour d'autres cas. Je ne sais pas une mise en œuvre qui l'utilisent pour autre chose que le chargement dynamique.

Revoyons un pseudo-code:

Dans DLL:

static int ItsDllVar = 1;
int EXPORTED_FUNCTION() { return ItsDllVar; }

En application:

static int AppVar1 = 2;
static int AppVar2 = EXPORTED_FUNCTION() + AppVar1;

Ainsi, selon AppVar2 statique initialisation obtient 1 + 2 = 3

initialisation Lazy applicable pour les variables statiques locales (indépendamment de DLL)

int f()
{
    static int local_i = 5;//it get's 5 only after visiting f()
    return local_i;
}

Je pense que ce qui est arrivé dans mon cas avec g ++ 4.7 et CMake (pas sûr si cela est un détail pertinent en ce qui concerne CMake). J'ai un code qui enregistre une fonction dans l'usine. Elle repose sur le constructeur appelant à partir d'une variable initialisée au niveau mondial.

Lorsque ce code est en l'initialisation Bibliothèque lié statiquement n'a pas eu lieu! Il travaille maintenant très bien, quand je l'ai déplacé aux fichiers objets liés directement (à savoir, ils ne sont pas combinés dans une première bibliothèque).

Alors, je pense que vous avez raison.

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