2009-01-07 6 views
1
  • environnement: linux, espace utilisateur-application créée par g ++ à partir d'un couple de fichiers C++ (résultat est un ELF)C++ cteur question (linux)

  • il y a un problème (SIGSEGV) lors de la traversée de la liste constructeur

 
    (__CTOR_LIST__) 

(Note: le code appelé via cette liste est une sorte d'initialisation du système pour chaque classe, pas le constructeur code je l'ai écrit)

  • quand je comprends bien chaque unité de compilation (tous les .O créé à partir d'un cpp) crée une entrée dans
 
    __CTOR_LIST__ 
  • le problème (SIGSEGV) n'existe pas quand je passe par GDB à travers le programme

  • pour le débogage cela je cherche un n façon d'ajouter votre propre code avant l'appel de

 
    "_do_global_ctors_aux" 

des conseils pour cela?

grâce,

Uwe

Répondre

1

Il est possible que vous être mordu par le soi-disant "Initialisation statique ordre Fiasco". Fondamentalement, lorsqu'il y a plus d'une unité de traduction (c'est-à-dire, fichier source C++), et que chaque fichier définit un objet global, le compilateur/éditeur de liens C++ ne peut pas établir quoi construire en premier. Si x dépend de y en cours de construction en premier, mais par la compilation/liaison accidentelle causes x à être construit avant y, le programme se bloque généralement. Voir l'article [10.12] du C++ FAQ Lite pour plus de détails. Le point [10.13] contient une solution - l'idiome «construire à la première utilisation».

7

Il existe de nombreuses raisons possibles à cela. Gammes à partir de laquelle vous accédez aux objets non encore créés (car l'ordre de création des objets entre les différentes unités de traduction est indéfini), ce qui est assez probable dans ce cas, et varie en une erreur sur votre environnement de construction.

Pour que votre propre fonction soit appelée avant une autre fonction de constructeur, vous avez un attribut constructor (priority) décrit here. GCC conserve une priorité pour la section d'entrée du constructeur de chaque fichier. Et cela les relie dans l'ordre de ces priorités. Dans le script éditeur de liens de mon système Linux, ce code ressemble à ceci (sortie à l'aide ld -verbose):

.ctors   : 
    { 
    /* gcc uses crtbegin.o to find the start of 
     the constructors, so we make sure it is 
     first. Because this is a wildcard, it 
     doesn't matter if the user does not 
     actually link against crtbegin.o; the 
     linker won't look for a file to match a 
     wildcard. The wildcard also means that it 
     doesn't matter which directory crtbegin.o 
     is in. */ 
    KEEP (*crtbegin.o(.ctors)) 
    KEEP (*crtbegin?.o(.ctors)) 
    /* We don't want to include the .ctor section from 
     the crtend.o file until after the sorted ctors. 
     The .ctor section from the crtend file contains the 
     end of ctors marker and it must be last */ 
    KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o) .ctors)) 
    KEEP (*(SORT(.ctors.*))) 
    KEEP (*(.ctors)) 
    } 

Vous voulez donner une priorité faible pour faire exécuter avant que d'autres fonctions ctor enregistrées ayant une priorité plus élevée nombre.Cependant, à première vue, il semble que les constructeurs n'ayant aucun numéro seront exécutés en premier. Pas tout à fait sûr. Le mieux c'est de l'essayer. Si vous voulez que votre fonction soit appelée avant _do_global_ctors_aux, vous devez libérer la fonction _init d'origine qui est normalement exécutée lorsque votre programme est chargé par le chargeur ELF (regardez dans l'option -init de ld). Cela fait un certain temps que je me suis trompé, mais je me souviens qu'il doit faire quelques détails intimes d'initialisation, donc je n'essaierais pas de le remplacer. Essayez d'utiliser l'attribut constructeur auquel je suis lié. Cependant, soyez très prudent. Votre code sera éventuellement exécuté avant que d'autres objets importants tels que cout ne soient construits.

Mise à jour: J'ai fait un test, et il exécute en fait les fonctions ctor en sens inverse. Ainsi, les fonctions ctor qui sont liées en premier sont exécutées plus tard. Ce code se trouve être dans crtstuff.c du code source gcc:

func_ptr *p; 
    for (p = __CTOR_END__ - 1; *p != (func_ptr) -1; p--) 
    (*p)(); 

J'ai fait un petit test:

void dothat() { } 
struct f { 
    f() { dothat(); } 
} f_; 
void doit() __attribute__((constructor (0))); 
void doit() { } 
int main() { } 

Établir des liens avec des rendements --print-map, entre autres, cette sortie:

.ctors   0x080494f4  0x10 
*crtbegin.o(.ctors)     
.ctors   0x080494f4  0x4 /usr/lib/gcc/i686-pc-linux-gnu/4.3.2/crtbegin.o 
*crtbegin?.o(.ctors)                 
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)           
.ctors   0x080494f8  0x4 /tmp/ccyzWBjs.o         
*(SORT(.ctors.*))                 
.ctors.65535 0x080494fc  0x4 /tmp/ccyzWBjs.o         
*(.ctors)                   
.ctors   0x08049500  0x4 /usr/lib/gcc/i686-pc-linux-gnu/4.3.2/crtend.o 

Notez comment .ctors.65535 est la section que nous avons implicitement créée par notre attribut de priorité 0. Maintenant, si vous donnez la priorité, gcc met en garde contre et il est tout à fait raison: p

test.cpp: 7: avertissement: priorités constructeur de 0 à 100 sont réservés à la mise en œuvre

Je l'ai testé il en cassant doit et dothat, et il les a appelés dans l'ordre que nous attendons. S'amuser!

0

pas la question que vous avez posée, mais ...

En C++/g ++, vous pouvez avoir une classe où les déclarées méthodes [en-tête] ne sont jamais réellement définis dans la source [.cc] fichiers aussi longtemps que ces méthodes ne sont jamais invoquées. En conséquence, vous pouvez copier vos fichiers de code actuels dans un répertoire temporaire, faire un travail de hack et de slash sur eux, lancer une recherche binaire [manuelle] et isoler le problème assez rapidement.

Pas élégant, mais très efficace.


En dehors de la « Initialisation statique Ordre » infâme question, il y a aussi des cas plus ésotériques comme celui récemment me le faisait remarquer ici sur SO by Charles Bailey (see the comments).

E.g Mixing: int p [] = { 1,2,3 }; 
      And: extern int * p; 

Produira un coredump similaire problème.