Troncation des noms à l'ancien format pour les instanciations de modèles exportés
Mise à jour : novembre 2007
Un aspect de la mise en conformité de Visual C++ est d'autoriser la surcharge de spécialisations de modèles de fonctions et de modèles normaux.
Par exemple, l'exemple suivant se compile dans Visual Studio .NET 2003, mais échouera dans Visual Studio .NET :
// bc_exported_templ_instan.cpp
template<typename T, typename U>
T ConvertTo(const U &u) {
return static_cast<T>(u);
}
char ConvertTo(const int &i) {
return static_cast<char>(i);
}
int main() {
char c1 = ConvertTo(1);
char c2 = ConvertTo<char, int>(2);
}
Pour prendre en charge la surcharge de spécialisations de modèles de fonctions et de modèles normaux, le compilateur a modifié la façon dont il crée les noms décorés pour les spécialisations de modèles de fonctions. Un nom décoré mis à jour inclut désormais un codage des arguments template, ainsi qu'un codage des paramètre de fonction et des types de retour. Pour les fonctions de l'exemple précédent, le compilateur C++ dans Visual Studio .NET 2003 générera les décorations de noms suivantes :
?ConvertTo@@YADABH@Z – char ConvertTo(const int &);
??$ConvertTo@DH@@YADABH@Z – char ConvertTo<char, int>(const int &);
Cela ne doit pas impliquer de modification dans la façon dont vous développez vos applications. Une zone où cette modification concerne les utilisateurs est si l'exportation est une spécialisation d'un modèle de fonction d'une DLL utilisée dans une application qui n'a pas été recompilée avec le nouveau compilateur. Par exemple :
// bc_exported_templ_instan2.h
#include <iostream>
#ifdef _DLL_EXPORT
#define DLL_LINKAGE __declspec(dllexport)
#else
#define DLL_LINKAGE __declspec(dllimport)
#endif
template<typename T>
void f(const T &rT) {
std::cout << "i = " << rT << std::endl;
}
template DLL_LINKAGE void f<int>(const int &);
Le code suivant sera compilé pour créer la DLL :
// bc_exported_templ_instan2.cpp
// compile with: /D_DLL_EXPORT /EHsc /LD
#include "bc_exported_templ_instan2.h"
Si vous faites ensuite :
dumpbin /exports bc_exported_templ_instan2.dll
Vous voyez que le nom décoré de la spécialisation exportée du modèle de fonction est ??$f@H@@YAXABH@Z.
Si une application existante a une dépendance sur cette DLL et que cette application a été générée avec le compilateur Visual C++ dans Visual Studio .NET (ou une version antérieure) et qu'ils ne peuvent pas ou ne souhaitent pas régénérer cette application, ils obtiendront alors une erreur d'exécution, car l'application attendra un point d'entrée avec l'ancien nom. Toutefois, la nouvelle DLL exportera uniquement une fonction avec le nouveau nom.
// bc_exported_templ_instan3.cpp
// compile with: /EHsc /link bc_exported_templ_instan2.lib
#include "bc_exported_templ_instan2.h"
int main() {
f(1);
}
Le correctif pour ce problème est de modifier la façon dont la DLL est générée de sorte qu'elle exportera à la fois l'ancien et le nouveau nom pour la spécialisation du modèle de fonction. Pour ce faire, utilisez /export vers le programme de liaison. Par exemple :
cl /D_DLL_EXPORT /EHsc /LD a.cpp /link /export:?f@@YAXABH@Z=??$f@H@@YAXABH@Z
Cela indique au lien de créer une exportation pour les noms spécifiés, mais pour faire en sorte qu'ils mappent au même symbole.