2010-05-06 4 views
12

Lors du développement d'une bibliothèque C++ SWIG pour Ruby, nous avons rencontré un crash inexpliqué lors de la gestion des exceptions dans le code C++.segfault pendant __cxa_allocate_exception dans la bibliothèque enveloppée SWIG

Je ne suis pas sûr des circonstances spécifiques pour recréer le problème, mais il est arrivé d'abord lors d'un appel à std::uncaught_exception, puis après quelques modifications de code, déplacé à __cxa_allocate_exception pendant la construction d'exception. Ni GDB ni valgrind n'ont fourni d'informations sur la cause de l'accident.

que j'ai trouvé plusieurs références à des problèmes similaires, y compris:

Le thème principal semble être une combinaison de circonstances:

  • application AC est lié à plus d'un C++ bibliothèque
  • Plus d'une version de libstdC++ a été utilisé lors de la compilation
  • En général, la deuxième version de C++ utilisé provient d'une implémentation binaire seulement libGL
  • Le problème ne se produit pas lors de la liaison de votre bibliothèque avec une application C++, uniquement avec une application C

La « solution » est de lier explicitement votre bibliothèque libstdC++ et peut-être aussi avec libGL, forçant l'ordre de liaison.

Après avoir essayé de nombreuses combinaisons avec mon code, la seule solution que j'ai trouvée qui fonctionne est l'option LD_PRELOAD="libGL.so libstdc++.so.6" ruby scriptname. Autrement dit, aucune des solutions de liaison au moment de la compilation n'a fait de différence.

Ma compréhension du problème est que l'exécution de C++ n'est pas initialisée correctement. En forçant l'ordre de liaison vous amorcez le processus d'initialisation et cela fonctionne. Le problème se produit uniquement avec les applications C appelant des bibliothèques C++ car l'application C n'est pas elle-même liée à libstdC++ et n'initialise pas l'exécution C++. Parce que l'utilisation de SWIG (ou boost :: python) est un moyen courant d'appeler une bibliothèque C++ à partir d'une application C, c'est pourquoi SWIG apparaît souvent lors de la recherche du problème.

Est-ce que quelqu'un peut donner plus d'informations sur ce problème? Existe-t-il une solution réelle ou n'existe-t-il que des solutions de contournement?

Merci.

+0

Trouvé la véritable cause du problème. Espérons que cela aidera quelqu'un d'autre à rencontrer ce bug. Vous avez probablement des données statiques quelque part qui ne sont pas correctement initialisées. Nous l'avons fait, et la solution était dans boost-log pour notre base de code. https://sourceforge.net/projects/boost-log/forums/forum/710022/topic/3706109. Le vrai problème est le retard bibliothèque chargée (plus statique), et non les versions potentiellement multiples de C++ de différentes bibliothèques. Pour plus d'informations: http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.13 – lefticus

+2

Vous devez copier ceci dans une réponse pour que les autres puissent voir plus facilement. –

Répondre

5

la suggestion de Michael Dorgan, je copie mon commentaire dans une réponse:

trouvé la cause réelle du problème. Espérons que cela aidera quelqu'un d'autre à rencontrer ce bug. Vous avez probablement des données statiques quelque part qui ne sont pas correctement initialisées. Nous l'avons fait, et la solution était dans boost-log pour notre base de code. https://sourceforge.net/projects/boost-log/forums/forum/710022/topic/3706109. Le vrai problème est la bibliothèque chargée en retard (plus les statistiques), pas les versions potentiellement multiples de C++ provenant de différentes bibliothèques.Pour plus d'informations: http://parashift.com/c++-faq-lite/ctors.html#faq-10.13

Depuis que j'ai rencontré ce problème et sa solution, j'ai appris qu'il est important de comprendre comment les statistiques sont partagées ou non entre vos bibliothèques liées dynamiquement et statiquement. Sous Windows, cela nécessite explicitement l'exportation des symboles pour les statistiques partagées (y compris des éléments tels que les singletons destinés à être accédés par différentes bibliothèques). Le comportement est subtilement différent entre chacune des plateformes majeures.

+0

Accepter cela comme une réponse aussi :) – sarnold

1

le même problème en utilisant SWIG pour Python avec une bibliothèque de cpp (Clipper), je trouve que l'utilisation LD_PRELOAD comme vous suggère des œuvres pour moi aussi. Comme une autre solution de contournement qui ne nécessite pas LD_PRELOAD, j'ai trouvé que je peux également lier le libstdC++ dans le fichier de bibliothèque .so de mon module, par exemple.

ld -shared /usr/lib/i386-linux-gnu/libstdc++.so.6 module.o module_wrap.o -o _module.so 

Je peux ensuite l'importer en python sans aucune autre option.

1

Je me rends compte que @lefticus a accepté la réponse relative à ce que je suppose que les montants à l'ordre d'initialisation statique non définie; Cependant, j'ai eu un problème très similaire, cette fois avec boost::python.

J'ai essayé mon damndest trouver des problèmes de initilisation statiques et ne pouvait pas - au point que je refactorisé une grande partie de notre base de code; et quand cela n'a pas fonctionné, il a fini par supprimer les exceptions.

Cependant, un peu plus rampé et nous avons commencé à ces segfaults à nouveau.

Après une enquête plus approfondie je suis tombé sur this link qui parle de allocateurs personnalisés.

Nous utilisons en effet nous tcmalloc; et après je l'ai enlevé de notre bibliothèque qui est exportée au boost::python nous n'avons eu aucun plus de problèmes! Donc juste un FYI pour quelqu'un qui trébuche sur ce fil - si la réponse de @ lefticus ne fonctionne pas, vérifiez si vous utilisez un allocateur différent de celui utilisé par python.

2

J'ai récemment rencontré ce problème également. Mon processus crée un module d'objet partagé qui est utilisé comme une extension C++ python. Une récente mise à niveau du système d'exploitation de RHEL 6.4 vers 6.5 a révélé le problème.

Suivant les conseils ici, je simplement ajouté -lstdC++ à mes commutateurs de liaison et qui a résolu le problème.