35 votes

Puis-je utiliser le compilateur C++ de Visual Studio 2010 avec la bibliothèque d'exécution C++ de Visual Studio 2008 ?

J'ai une application qui doit fonctionner sous Windows 2000. J'aimerais également utiliser Visual Studio 2010 (principalement en raison de la modification de la définition de l'attribut auto mot-clé). Cependant, je suis un peu dans le pétrin car j'ai besoin que l'application puisse fonctionner sur des OS plus anciens, à savoir :

  • Windows 2000
  • Windows XP RTM
  • Windows XP SP1

La bibliothèque d'exécution de Visual Studio 2010 dépend du fichier EncodePointer / DecodePointer qui a été introduit dans Windows XP SP2.

Si l'utilisation de la bibliothèque d'exécution alternative est possible, cela va-t-il casser le code qui repose sur les fonctionnalités C++0x ajoutées dans VS2010, telles que std::regex ?

24voto

AshleysBrain Points 11439

La solution la plus simple est de définir le Platform Toolset dans les paramètres du projet dans VS2010 sur v900, ce qui utilisera les bibliothèques et le compilateur de Visual Studio 2008. Cela signifie également que vous perdez les fonctionnalités C++0x telles que auto mais pour être honnête, travailler autour de ça avec quelques typedef est probablement plus facile que de construire votre propre version du CRT ou d'autres solutions plus compliquées. Sinon, il suffit d'utiliser VS2008 ! Je ne sais pas s'il y a d'autres fonctionnalités de C++0x qui sont critiques pour votre application, vous n'avez pas mentionné - autre que std::regex qui, je pense, se trouve encore dans la boîte à outils v900 sous l'espace de nom du rapport technique 1 ( std::tr1::regex ).

D'après l'impression que j'ai, je dirais que l'inconvénient de faire fonctionner les bibliothèques VS2010 sur XP SP1 est plus grand que la commodité des fonctionnalités C++0x, donc globalement cela ne vaut pas la peine.

23voto

Suma Points 11966

Vous ne pouvez pas utiliser le CRT 2008, mais vous pouvez empêcher les nouvelles fonctions DecodePointer/EncodePointer d'être liées à partir du noyau. Il est assez facile de remplacer ces nouvelles fonctions par des stubs.

On pourrait essayer de suivre : Placez un code comme celui-ci dans votre source main.cpp :

~~extern "C" {

  void *__stdcall _imp__DecodePointer(void *x) {return x;}
  void *__stdcall _imp__EncodePointer(void *x) {return x;}

};~~ 

Ce qui précède ne fonctionne pas. Si l'idée de base est bonne, l'exécution doit être un peu différente. Comme décrit par snemarch dans le commentaire et une autre réponse , __imp__ ne peut pas être l'appel de la fonction, seulement le pointeur vers celle-ci. Comme il ne semble pas possible de générer le pointeur directement par le compilateur, vous devez assembler le code suivant avec MASM et le lier au fichier objet produit.

.model flat

.data
__imp__EncodePointer@4 dd dummy
__imp__DecodePointer@4 dd dummy
EXTERNDEF __imp__EncodePointer@4 : DWORD
EXTERNDEF __imp__DecodePointer@4 : DWORD

.code
dummy proc
mov eax, [esp+4]
ret 4
dummy endp

end

Les symboles d'un projet ont la préférence sur les symboles des bibliothèques. Les bibliothèques DLL sont liées à l'aide de parties .lib, qui contiennent seulement __imp__ "vecteurs" sautant dans les fonctions réelles. En remplaçant __imp__ "vecteurs" vous ne touchez pas à la liaison DLL, vous remplacez la partie .lib. J'ai vérifié qu'il n'y a plus de dépendance de l'exe sur DecodePointer / EncodePointer.

Contexte

Une bibliothèque liée statiquement apporte uniquement la fonctionnalité utilisée dans l'application. Il est possible de trouver quelle fonction particulière de la CRT apporte ces nouvelles API en utilisant la sortie de progression verbeuse du linker :

Found __imp__EncodePointer@4
  Referenced in LIBCMT.lib(crtmboxw.obj)
  Referenced in LIBCMT.lib(invarg.obj)
  Referenced in LIBCMT.lib(handler.obj)
  Referenced in LIBCMT.lib(onexit.obj)
  Referenced in LIBCMT.lib(cmiscdat.obj)
  Referenced in LIBCMT.lib(tidtable.obj)
  Referenced in LIBCMT.lib(hooks.obj)
  Referenced in LIBCMT.lib(winsig.obj)
  Referenced in LIBCMT.lib(rand_s.obj)

Found __imp__DecodePointer@4
  // ... same list, only order differs ... 

Cela montre que les nouvelles API sont utilisées dans certains des CRT pour renforcer la sécurité de certaines fonctions qui sont considérées comme des vecteurs d'attaque fréquents.

Avec un peu d'effort, il serait possible d'utiliser LoadLibrary / GetProcAddress pour fournir la vraie fonctionnalité là où l'OS l'offre, mais je ne pense pas que cela apporterait vraiment quelque chose. Les fonctions d'exécution qui utilisent DecodePointer / EncodePointer n'ont pas vraiment besoin de fournir un encodage, tout ce dont elles ont besoin est que l'encodage soit symétrique. Vous n'avez pas vraiment besoin de la sécurité renforcée (le runtime de VS 2008 ne vous la donnerait pas non plus).

J'espère qu'il n'y a pas d'autres obstacles qui vous attendent - Je n'ai pas accès à un système Win2k ou XP pre SP2, donc je ne peux pas essayer. S'il y a des drapeaux d'en-tête d'exe qui empêchent même de tenter de lancer l'exe sur ces systèmes, ils devraient être faciles à changer.

11voto

snemarch Points 3328

La solution de Suma semblait plutôt prometteur, mais cela ne fonctionne pas : la __imp__*@4 Les symboles doivent être pointeurs aux fonctions, plutôt que les fonctions elles-mêmes. Malheureusement, je ne sais pas comment faire pour que Visual C++ crache un pointeur avec ce genre de génération de noms... (enfin, __declspec(naked) combiné avec __stdcall fait l'affaire, mais alors je ne sais pas comment émettre un pointeur).

Si l'utilisation d'un assembleur au moment de la construction est acceptable, la solution est assez triviale - assembler le code suivant avec FASM et lier avec le fichier objet produit, et presto - aucune référence EncodePointer/DecodePointer dans l'exe :

use32
format ms coff

section ".data" data
public __imp__DecodePointer@4
__imp__DecodePointer@4 dd dummy

public __imp__EncodePointer@4
__imp__EncodePointer@4 dd dummy

section ".text" code
dummy:
mov eax, [esp+4]
retn 4

8voto

Tomasz Grobelny Points 886

Comme Visual Studio est livré avec un support pour MASM (voir les propriétés du projet -> Build Customizations...), la traduction suivante du code de snemarch en MASM pourrait être utile :

.model flat

.data
__imp__EncodePointer@4 dd dummy
__imp__DecodePointer@4 dd dummy
EXTERNDEF __imp__EncodePointer@4 : DWORD
EXTERNDEF __imp__DecodePointer@4 : DWORD

.code
dummy proc
mov eax, [esp+4]
ret 4
dummy endp

end

Et n'oubliez pas de définir Linker->System->Minimum Required Version à 5.0 (la valeur par défaut est 5.1) pour fonctionner sous Windows 2000.

4voto

Head Geek Points 10874

La solution habituelle à ce problème est de construire votre propre version personnalisée du CRT. Il y a des instructions pour cela aquí . Vous devrez juste modifier le code pour ignorer EncodePointer y DecodePointer . (Il devrait déjà y avoir un #define pour ça.)

Il y a deux autres petites choses que vous devrez faire :

  • Allez dans le paramètre Linker->Additional Library Directories et mettez le paramètre C:\Microsoft Visual Studio 9.0\VC\lib comme premier chemin à rechercher. (Je suppose que vous avez utilisé le répertoire d'installation par défaut, sinon modifiez comme il convient).
  • Changez la version du sous-système, dans l'en-tête PE, en 5.00 (utilisez le logiciel gratuit Suite de l'explorateur CFF si vous n'avez pas d'autre outil à portée de main pour cela).

Cela devrait permettre à votre programme de fonctionner sur Windows 2000 ainsi que sur les versions ultérieures.

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