13 votes

Erreur de liaison "bad codegen, pointer diff" avec Xcode 4

En recompilant une application iPhone C++ avec Xcode 4, j'obtiens cette méchante erreur de linker :

ld: bad codegen, pointer diff in __static_initialization_and_destruction_0(int, int)
to global weak symbol vmml::Vector2<float>::ZERO for architecture armv6

Quelqu'un sait ce que ça veut dire ? Et comment le faire disparaître, bien sûr :)

L'application a été compilée et liée sans erreur dans Xcode 3.

Editar la solution consiste à définir Symboles cachés par défaut a Oui dans tous les paramètres de construction de toutes les cibles du projet. Je ne sais toujours pas quel est le problème réel.

18voto

Rob Agar Points 5793

La solution consiste à définir Symbols Hidden By Default a Oui dans tous les paramètres de construction de toutes les cibles du projet. Je ne sais toujours pas quel est le problème réel.

5voto

Tyler Daniel Points 209

J'ai eu le même problème et j'ai également fini par ajuster les paramètres de visibilité. Cependant, comme j'étais nerveux à l'idée de jouer avec la visibilité des symboles sans comprendre le problème, j'ai poussé un peu plus loin mes recherches.

Si, comme moi, vous utilisez le script/package de Pete Goodliffe pour construire boost comme un framework, le script fixe la visibilité par défaut à hidden (== yes). Les options de visibilité changent la façon dont les symboles sont marqués par le compilateur (par défaut, caché, interne). Cette information est utilisée par l'éditeur de liens lors de la création d'objets partagés (bibliothèques partagées). Elle ne devrait pas s'appliquer ici, donc je soupçonne que c'est un bug de l'éditeur de liens. Dans la bibliothèque boost, vous avez un symbole faible marqué comme caché, et ensuite dans votre projet/autre bibliothèque, le même symbole marqué comme défaut. L'éditeur de liens est confus ?

En ce qui concerne XCode 3 par rapport à 4, peut-être que le défaut dans 3 était de cacher les symboles ?

Quoi qu'il en soit, le fait de changer la visibilité par défaut en cachée ne devrait avoir aucun effet si seules des librairies statiques sont concernées, et je me sens donc beaucoup plus en sécurité en prenant cette voie.

J'ai posté un peu plus de détails dans un entrée de blog pour les personnes intéressées.

4voto

zim Points 506

J'ai rencontré ce problème en essayant d'inclure les bibliothèques boost dans un de mes projets. Après avoir trouvé ce post, en mettant Symbols Hidden By Default a Yes a également résolu ce problème pour moi. Et j'ai également dû effectuer le même réglage dans chacun des projets dépendants pour me débarrasser complètement de l'erreur.

Juste pour info - Cela ne s'est produit que sur mes cibles qui utilisaient la pile clang++. Les cibles GCC et LLVM+GCC ne semblent pas être affectées.

2voto

Andrew Haining Points 21

En fait, tous les symboles d'une bibliothèque que vous liez à votre propre code doivent utiliser le même niveau de visibilité, c'est-à-dire que si tous les symboles d'une bibliothèque que vous incluez sont cachés, vous devez vous assurer que les fichiers d'inclusion référençant les symboles dans votre projet n'essaient pas de les rendre visibles. La façon la plus sûre de procéder est d'avoir un niveau constant de visibilité par défaut dans tout votre projet.

1voto

markshiz Points 1040

Vous utilisez peut-être une bibliothèque qui contient des informations cachées sur les symboles. Si un symbole n'a pas été exporté de votre bibliothèque et que vous tentez de l'utiliser en externe, une erreur de liaison similaire se produit. La bonne solution semble être de trouver un moyen de rendre ce symbole "visible" au monde extérieur via les définitions de macro du GCC et/ou de modifier la bibliothèque elle-même pour s'assurer que ce symbole particulier est vraiment "caché" au monde extérieur - c'est-à-dire qu'il n'est pas utilisé ou exposé dans un fichier d'en-tête.

Toutefois, soyez prudent : selon la documentation d'Apple, vous ne devez pas masquer certaines informations relatives aux symboles pour un certain nombre de raisons ; celle qui est énumérée ci-dessous semble être la plus alarmante d'entre elles :

Si votre symbole utilise des informations d'identification de type d'exécution (RTTI), des exceptions ou des castings dynamiques pour un objet défini dans une autre bibliothèque, votre symbole doit être visible s'il compte traiter les demandes initiées par l'autre bibliothèque. Par exemple, si vous définissez un gestionnaire de capture pour un type dans la bibliothèque standard C++ et que vous voulez attraper les exceptions de ce type lancées par la bibliothèque standard C++, vous devez vous assurer que votre objet typeinfo est visible.

Fuente: http://developer.apple.com/library/mac/#documentation/DeveloperTools/Conceptual/CppRuntimeEnv/Articles/SymbolVisibility.html

Ainsi, si vous voulez attraper une exception de la bibliothèque avec laquelle vous établissez un lien, cacher les informations sur les symboles semble être un mauvais choix. La solution correcte serait de démasquer les symboles de la bibliothèque à laquelle vous vous connectez. Cela peut être fait soit par en omettant les drapeaux suivants du compilateur GCC :

-fvisibility=hidden --fvisibility-inlines-hidden

(la visibilité par défaut devrait être suffisante), ou il existe également des pragmas de compilation qui vous permettent de le faire. Voir : http://gcc.gnu.org/wiki/Visibility

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X