4 votes

Pourquoi un fichier .lib compilé dans VS2003 ne pourrait-il pas être lié à un code compilé dans VS2008 ?

Nous venons de vivre une expérience intéressante en essayant de lier un ensemble de code compilé avec Visual Studio Express 2008 avec un .lib compilé avec Visual Studio 2003. Le tout en C++. Pour être précis, il s'agissait de la SystemC 2.2.0 qui a été compilé en VS2003 dans un fichier .lib, et un modèle SystemC qui a été compilé en VS2008.

Lors de l'édition des liens, nous avons obtenu l'erreur que quelques symboles du fichier SystemC.lib (c.-à-d. compilé dans VS2003) n'ont pas été trouvés pendant l'édition des liens. L'erreur que nous obtenions était la suivante (en quelques variantes) :

SystemC.lib(sc_port.obj) : error LNK2001: unresolved external symbol "public: vo
id __thiscall std::_String_base::_Xran(void)const " (?_Xran@_String_base@std@@QB
EXXZ)

En creusant à partir de différentes pistes, il s'est avéré que la fonction que le fichier .lib s'attendait à trouver était la suivante :

Undecoration of :- "?_Xran@_String_base@std@@QBEXXZ"
is :- "public: void __thiscall std::_String_base::_Xran(void)const "

Le fichier de bibliothèque avec lequel VS2008 essayait d'établir un lien (libcpmt.lib) utilisait une convention d'appel différente :

Undecoration of :- "?_Xran@_String_base@std@@SAXXZ"
is :- "public: static void __cdecl std::_String_base::_Xran(void)"

J'ai essayé de comprendre pourquoi cette incompatibilité se produisait, mais j'ai fini par abandonner, j'ai recompilé exactement le même projet visual studio dans VS2008, et j'ai utilisé ce SystemC.lib au lieu de celui de VS2003. Maintenant, les choses fonctionnent parfaitement.

La question fondamentale est donc la suivante : qu'est-ce qui a changé entre VS2003 et VS2008 pour que certaines fonctions changent leurs conventions d'appel ? Existe-t-il un drapeau magique à donner à l'éditeur de liens dans VS2008 pour utiliser une autre bibliothèque où les fonctions ont la même convention d'appel que dans la compilation VS2003 ?

Mise à jour, résumé des réponses jusqu'à présent : Il est très probable que Microsoft modifie l'ABI C++ (pas C, juste C++) d'une version majeure de Visual Studio à l'autre. Il peut également y avoir d'autres changements dans les bibliothèques qui causent des incompatibilités. Le meilleur conseil est de recompiler la bibliothèque .lib pour chaque version de VS. En fait, il suffit d'envoyer le code source aux utilisateurs et de leur demander de le compiler localement en utilisant la version de VS qu'ils ont installée.

Le problème de base a été découvert en utilisant le conseil dans :

Il est à noter que ces questions n'ont pas répondu à cette problématique :

3voto

yves Baumes Points 4521

Il n'existe pas de norme pour l'ABI C++. Cela signifie que tous les compilateurs C++ peuvent gérer une ABI différente d'un compilateur à l'autre, et cela inclut les différentes versions d'un même compilateur. Vous pourriez avoir le même problème avec deux versions majeures différentes de Gcc. Une telle modification pourrait se produire lorsqu'ils trouveront un moyen d'améliorer l'étape d'édition de liens.

Mais l'ABI implique bien plus que cela. Par exemple, la manière dont les tables virtuelles sont stockées et gérées par le code généré par le compilateur. Si cela change, vos objets et votre code généré en 2008 ne seront pas compatibles avec la bibliothèque qui s'attend à ce que cela se fasse de la même manière qu'en 2003.

À ce stade, vous pouvez comprendre pourquoi les bibliothèques c++ sont livrées avec leur code source ou compilées sur un ordinateur. nombreux différentes architectures et compilateurs.

En général, lorsqu'on écrit une bibliothèque, on la développe en langage C, et non en langage C++, afin d'éviter ce genre de problèmes. Comme le langage C dispose d'une ABI standardisée, vous pouvez le compiler avec un compilateur et ensuite lier cette bibliothèque avec n'importe quel compilateur C qui respecte cette ABI standard. Par exemple, la façon dont les chaînes de caractères sont implémentées est standard et ne changera probablement jamais (la fameuse chaîne à terminaison nulle). Alors que l'implémentation de std::string change d'une version majeure de Gcc à l'autre (il suffit de regarder la classe basic_string dans les fichiers /usr/include/c++/x.x/bits/basic_string).

2voto

Diaa Sami Points 1802

Pour autant que je sache, ces problèmes surviennent à cause de la bibliothèque CRT, ils changent avec les versions majeures et vous ne devriez pas mélanger les types de CRT (multithreaded, debug, release, static, dynamic, etc).

J'ai réussi à réutiliser les bibliothèques de VS2003 dans VS2005 mais c'est ennuyeux, il vaut mieux recompiler l'ensemble. Parfois, vous pouvez vous en sortir en utilisant l'option /NODEFAULTLIB pour éviter l'édition de liens avec une certaine bibliothèque CRT qui pose des problèmes.

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