en C ++, je sais que le compilateur peut choisir d'initialiser les objets statiques dans n'importe quel ordre qu'elle choisit (sous réserve de quelques contraintes) et que, en général, vous ne pouvez pas choisir ou déterminer l'ordre d'initialisation statique. P>
Cependant, une fois qu'un programme a été compilé, le compilateur doit avoir décidé de la décision de l'ordre d'initialiser ces objets. y a-t-il un moyen de déterminer, d'un programme compilé avec des symboles de débogage, dans quel ordre Les constructeurs statiques seront appelés? strong> p>
Le contexte est ceci: j'ai un programme considérable qui se sépare soudainement avant la construction principale () lorsqu'il est construit sous une nouvelle boîte à outils. Soit ceci est un problème d'ordre d'initialisation statique, soit quelque chose qui ne va pas avec l'une des bibliothèques de chargement. Cependant, lorsque je débogé avec GDB, l'emplacement du crash est simplement signalé comme une adresse brute sans aucune information ou retour symbolique. J'aimerais décider lequel de ces deux problèmes est en plaçant un point d'arrêt sur le constructeur du tout premier objet statiquement initialisé, mais je ne sais pas comment dire quel objet qui est. P>
6 Réponses :
Pourriez-vous initialiser des variables factices dans l'espace statique et mettre des points de rupture sur ces appels de fonction?
extern "C" int breakOnMe () { return 0 }; int break1 = breakOnMe (); float pi = 3.1415; int break2 = breakOnMe (); myClass x = myClass (1, 2, 3);
Est-il garanti que les variables statiques non-objets seront toujours initialisées avant que des objets statiques?
Dans Linux, les types de POD seront initialisés en les plaçant dans la section de données - ceux-ci seront chargés avant que tout code d'utilisateur ne soit exécuté.
Mais vous ne pouvez pas casser la section de données, la question est donc si un type de pod est initialisé au moyen d'un appel à une fonction (comme avec Break1 et Break2 dans l'exemple de Eduffy), est-ce garanti pour arriver avant que les constructeurs d'objets obtiennent appelé?
@Tyler, non, ils sont initialisés comme les appels de constructeur sont. Dans mes tests limités, ils semblent être initialisés par ordre de déclaration, mais cela peut ne pas être garanti.
@bdonlan: dans une unité de compilation. Cette commande est garantie.
Mais c'est bien sûr tout le problème - j'ai de nombreuses unités de compilation.
en G ++ sur Linux, le constructeur statique et la commande destructeurs sont déterminés par des pointeurs de fonction dans les sections .CTORS et .DTors. Notez que, avec suffisamment de débogage disponible, vous pouvez réellement obtenir une backtrage: Ceci est avec les symboles de débogage pour libc et libstdc ++ installé. Comme vous pouvez le constater, le crash est arrivé ici dans le constructeur FOO :: FOO () pour l'objet statique FOO_INST. P> Si vous souhaitez casser dans le processus d'initialisation, vous pouvez alors définir un point d'arrêt sur __do_global_ctors_aux et Passez à travers son désassemblage, je suppose. Ou attendez simplement que cela se bloque pour obtenir le backtrace comme ce qui précède. P> p>
Sur Quelques plates-formes i> cette réponse est correcte. Sur d'autres plates-formes, c'est faux. Vous ne devriez probablement pas supposer que "le monde entier est fait de binaires elfe".
Matthew Wilson fournit un moyen de répondre à cette question dans Cette section (Safari Books en ligne Abonnement requis) de imparfait c ++ i> a>. (Bon livre, au fait.) Pour résumer, il crée un Ceci nécessite une recompilation, mais le #include "cuttrace.h" peut facilement être ajouté et supprimé via un script, il ne devrait donc pas être trop difficile de configurer. P> cuttrace.h code> en-tête qui crée une instance statique d'une classe qui imprime le nom de fichier de fichier y compris (à l'aide du préprocesseur non standard Macro < Code> __ base_file __ code>) Lors de la création, il comprend
cuttrace.h code> dans chaque fichier source. P>
Idée très intelligente. Je vais essayer cela plus tard aujourd'hui et acceptera probablement cette réponse si cela fonctionne.
Bien que cela ne réponde pas exactement à ma question en soi, cela a résolu le problème qui a inspiré la question. En utilisant cette méthode, j'ai pu constater que le problème s'est produit avant toute initialisation statique de mon application et en modifiant les bibliothèques utilisées pour faire la même chose, j'ai pu déterminer quelle bibliothèque avait le problème. Il était alors beaucoup plus facile de trouver le bogue d'initialisation statique car cette bibliothèque a fait beaucoup moins d'initialisation statique que mon application.
g ++ fournit de l'aide avec cela.
Ce n'est pas portable mais je suis sûr à ce stade qui n'est pas votre problème principal. P>
http://gcc.gnu.org/onlineDocs /gcc/c_002b_002b-attributes.html#c_002b_002b-attributes P>
Vous pouvez trouver la commande que les TU sont initialisés à l'aide de modèles comme en surbrillance par cette Question . Il nécessite un petit morceau de code de code à chacun des TU qui vous intéresse:
static const char * SRC_FILE=__FILE__; #include "order.h" int main () { }
En réalité, grâce à l'utilisation de singletons, vous pouvez contrôler l'ordre de l'initialisation des objets globaux / statiques de manière assez efficace en C ++.
Par exemple, dites que vous avez: P>
//..some code global().abc.foo(); //..more code here global().def.bar();
Avez-vous essayé de recompiler avec le drapeau "-g3"? Cela devrait mettre de nombreux symboles de débogage pour que vous puissiez travailler avec.
C'est la liaison qui détermine la commande finale dans toutes les unités de compilation. Je crois que G ++ a des pragmes qui peuvent aider à définir la commande.
La réponse est très spécifique à la plate-forme et vous avez réussi à garder votre plate-forme un secret. S'il vous plaît, révélez-le, ainsi que la version de GDB que vous avez utilisée.
De plus, veuillez afficher la trace de la pile GDB que vous avez obtenue. Est susceptible de contenir des indices importants.
Juste pour répondre à ceux-ci, c'était Linux / g ++, et il n'y avait littéralement pas de trace de pile que ce soit (juste une seule adresse mémoire), même avec le débogage complet sur le programme et également sur la ou les bibliothèques, y compris la bibliothèque qui a finalement été le problème. Je n'ai toujours aucune idée pourquoi c'était.