7
votes

Double initialisation d'un conteneur STL statique dans une bibliothèque C ++

Il y a quelques bonnes questions et réponses ici autour du "Fiasco d'ordre d'initialisation statique", mais je semble avoir frappé encore une autre expression de celle-ci, spécialement laide, car elle ne se bloque pas mais ne fait pas des données.

J'ai une bibliothèque C ++ personnalisée et une application qui lie. Il existe un conteneur STL statique dans la bibliothèque qui enregistre toutes les instances d'une classe. Ces instances sont des variables statiques dans l'application.

à la suite du "fiasco" (je crois), nous obtenons le conteneur rempli des instances d'application lors de l'initialisation de l'application, la bibliothèque doit alors initialiser Et le conteneur est réinitialisé (probablement la mémoire qui fuit), se terminant uniquement avec les instances de la bibliothèque.

Voici comment je l'ai reproduit avec un code simplifié:

MyLib. HPP: xxx

myLib.cpp: xxx

myapp.cpp: xxx

compilez les objets avec: xxx

exécuté myApp1: xxx

exécuté myApp2: xxx

voici la question, Le vecteur statique a été réinitialisé ou utilisé avant l'initialisation? Est-ce un comportement attendu?

si je suis "ar" la bibliothèque comme "myLib.a" (ar rcs mylib.a myLib.o), le problème ne se produit pas, mais probablement parce que Il n'y a qu'un seul ordre valide de créer un lien vers le .a et c'est en ayant la bibliothèque en dernier lieu, comme pour myApp1 ici.

mais dans notre application réelle, un plus complexe avec de nombreux fichiers d'objets et quelques bibliothèques statiques (.a) partageant quelques registres statiques, le problème se produit et le seul moyen que nous ayons réussi à le résoudre à ce jour en appliquant '[10.15] Comment empêcher le" FIASCO d'ordre d'initialisation statique "? <.

(je suis toujours recherchée Dans notre système de construction quelque peu complexe de voir si nous relions correctement).


1 commentaires

Très beau code d'échantillon au fait. Je souhaite que toutes les questions ressemblaient à ceci.


3 Réponses :


3
votes

Si vous donnez vecteur un constructeur personnalisé que vous verrez, qu'il est bien appelé qu'une seule fois, mais dans myApp2 vous utilisez registre < / Code> Uninitialisé en premier, il est initialisé ("supprimer" tout ce qui est à l'intérieur) puis rempli. Que ce n'est pas Segfault n'a pas de chance :)

Je ne peux pas dire quelle partie de la norme dit quelque chose à propos de ce comportement, mais je devrais / jamais / laisser des variables statiques dépendent l'une de l'autre. Vous pouvez utiliser un meyers singleton par exemple pour le registre.


2 commentaires

En effet, c'est la solution que nous avons choisi, mais je ne savais pas que c'était "Meyer's".


Scott Meyers est le nom. Je pense qu'il a été le premier à proposer cette mise en œuvre du singleton dans son "plus efficace C ++".



4
votes

Un moyen de contourner les problèmes d'ordre d'initialisation consiste à déplacer les variables statiques de la portée globale à la portée locale.

au lieu d'avoir une variable de registre dans la classe, placez-la dans une fonction: xxx

dans les endroits où vous auriez utilisé directement le registre directement, avez-vous appeler getregistry . < / p>


2 commentaires

Je choisis cette réponse car il fournit un code d'échantillon clair. Après la recherche, il semble également être aussi de Meyer, comme mentionné ci-dessus.


@gatopeich, ouais je l'ai regardé après avoir vu l'autre réponse, mais je ne savais jamais que cela avait un nom.



0
votes

Vous utilisez 2 techniques connues.

(1) "Module / Bibliothèque / Espace de noms" comme modèle "Device"

(2) enregistrement de type personnalisé, avec une classe statique. < / p>

fait quelque chose de similaire avec "objet Pascal" et "plaine C". J'ai plusieurs fichiers, chaque fichier fonctionnant en tant que module / espace de noms, avec Typefefs, classes, fonctions. De plus, chaque "espace de noms" avait 2 méthodes spéciales (même signature ou prototype), qui simulent la connexion d'un périphérique et la déconnexion d'un périphérique. Déjà essayé d'appeler ces méthodes automatiquement, mais l'exécution de l'ordre a également mal tourné.

statique, les classes singletons peuvent devenir un gâchis. Je suggère, oublie d'utiliser des macros ou du préprocesseur / compilateur et appelez vous-même vos méthodes d'initialisation / de finalisation vous-même . xxx

Vérifiez que ce code est plus complexe et verbeux que le tien, Mais, dans mon expérience, est plus stable.

J'ajoute également "finaliseur" à "Initializer" et remplacer l'identifiant pour "registre".

Bonne chance.


0 commentaires