6
votes

Les objets de types intégrés ont-ils une ordonnance d'ordre d'initialisation statique spéciale?

J'aurais attendu que le code suivant donne une erreur de segmentation (ou sinon ub): xxx

c'est parce que t est initialisé avant STR . Je m'attendrais à str pour contenir la valeur (chartons *) 0 en raison d'une initialisation zéro. Mon interprétation de [C ++ 11: 3.6.2 / 2] prend en charge cela.

Cependant, L'extrait ci-dessus semble émettre la chaîne comme prévu comme prévu (et j'ai confirmé le comportement en imprimant également la valeur du pointeur).

existe une règle d'initialisation statique que je 'M Manquant ici, cela permet à str d'être initialisé avant que t commence la construction? Où est-il dans la norme?


Ceci est venu sur résolution de variable statique à la limite de la construction , où un répondeur a affirmé que l'utilisation de chartons * plutôt que std :: string pour un global statique évite le fiasco d'ordre d'initialisation statique. Je suis en désaccord, mais maintenant je ne suis pas si sûr ...


2 commentaires

Voir Stackoverflow.com/q/790687/34509 pour une question qui a actuellement accepté mais malheureusement mauvaise réponse.


@ Johannesschab-LitB: En effet.


4 Réponses :


1
votes

Les types intégrés ne sont pas initialisés du tout, au sens normal. Communément, leurs contenus initiaux sont cartographiés directement à partir d'une région spéciale du binaire dans le cadre de la chargement.


3 commentaires

S'avère qu'ils sont. Cet acte est apparemment appelé "initialisation constante".


@LighessRacksinorbit: logiquement, oui. Physiquement, vous ne trouverez aucun code nulle part indiquant: "Attribuez l'adresse de cette chaîne littérale à str ". C'est ce que je voulais dire, "au sens normal".


hoche la tête merci. Cherchait cependant de raisonner standard, donc logique.



6
votes

str est initialisé par une expression constante et const char * est un type de pod (C ++ 03 termes, mais c ++ 11 il est analogue, mais avec Termes et cas de manière différente des cas plus autorisés). Une telle initialisation est effectuée dans statique phase d'initialisation et la phase d'initialisation statique n'a pas de problème de commande. Cela arrive avant tout initialisation dynamique . t est initialisé dans la phase d'initialisation dynamique .


4 commentaires

Est-ce couvert par le passage que j'ai cité? Ou ailleurs?


@Light oui vous avez cité le texte C ++ 11.


Je ne suis pas convaincu que "STR est initialisé par une expression constante". Il faut une adresse de littéral de chaîne, ce qui n'est certainement pas une expression constante. Par conséquent, SH devrait avoir une initialisation dynamique. Cependant, les implémentations sont autorisées (3.6.2 / 3) pour l'initialiser de manière statique.


@Timo: Je suis sûr qu'un littéral à chaîne est une expression constante. Tous les littéraux doivent être ( 5.19 / 2 ). Que la valeur du pointeur peut changer entre les constructions et les invocations n'est pas pertinente.



0
votes
char const* str = "Test string";
is done by the compiler/linker, so it exists in its "initialized state" before the program even starts to run.

0 commentaires

1
votes

Je pense que je l'ai trouvé; Ce qui se passe ici n'est pas tant sur le type intégré, mais sur l'initialiseur constant:

[C ++ 11: 3.6.2 / 2]: Les variables avec durée de stockage statique (3.7.1) ou la durée du stockage de thread (3.7.2) doivent être initialisées zéro (8.5) avant toute autre initialisation a lieu.

initialisation constante est effectuée:

  • Si chacun expression complète (y compris les conversions implicites) qui apparaît dans l'initialisateur d'une référence avec une durée de stockage statique ou de thread est une expression constante (5,19) et la référence est liée à une adressage de la lvalue un objet avec durée de stockage statique ou à un temporaire (voir 12.2);
  • Si un objet avec une durée de stockage statique ou de thread est initialisé par un appel de constructeur, si le constructeur est un constructeur consexpr , si tous les arguments du constructeur sont des expressions constantes (y compris des conversions), et si, après Substitution d'invocation de fonction (7.1.5), chaque appel de constructeur et expression complète dans Les initialiseurs Mem-initialiseurs et dans les initialiseurs pour les membres de données non statiques sont une expression constante;
  • Si un objet avec une durée de stockage statique ou de fil n'est pas initialisé par un appel de constructeur et si chaque expression complète qui apparaît dans son initialiseur est une expression constante. < / li>

    ensemble, l'initialisation zéro et une initialisation constante s'appelle une initialisation statique; Toute autre initialisation est l'initialisation dynamique. L'initialisation statique doit être effectuée avant que toute initialisation dynamique n'a lieu. [..]

    Cette phrase finale semblerait remplacer les règles de séquençage ultérieures, ce qui rend cette commande s'appliquer sur des unités de traduction.


5 commentaires

Votre dernière conclusion est incorrecte. Seule initialisation dynamique peut être "non ordonnée" ou "commandée". Ces deux termes ne s'appliquent pas à l'initialisation statique. La commande n'est pas un problème ici.


@ Johannesschab-LitB: OK, que diriez-vous des deux phrases précédentes, qui répètent à peu près la même règle, mais sans le mot "non ordonné"?


Ils disent que "l'initialisation statique doit être effectuée avant que toute initialisation dynamique n'a lieu.". C'est une exigence difficile. Il n'y a pas de place pour les implémentations pour ne pas suivre cette exigence.


@ Johannesschab-Litb: Hmm ... Je suppose .. va revisiter


@ Johannesschab-Litb: Gotcha.