Que signifie la cible «Any CPU» de Visual Studio?

496

J'ai une certaine confusion liée aux options de génération de la plate-forme .NET dans Visual Studio 2008.

Qu'est-ce que la cible de compilation "Any CPU" et quel type de fichiers génère-t-elle? J'ai examiné l'exécutable de sortie de cette version "Any CPU" et j'ai découvert qu'il s'agissait des exécutables x86 (qui ne verraient pas cela arriver!). Alors, y a-t-il une différence entre le ciblage de l'exécutable sur x86 et "Any CPU"?

Une autre chose que j'ai remarquée, c'est que les projets C ++ gérés n'ont pas cette plate-forme en option. Pourquoi donc? Est-ce que cela signifie que mes soupçons à propos des exécutables "Any CPU" sont de simples 32 bits?

galets
la source
4
Une dernière chose à considérer lors du choix de la cible de plate-forme à utiliser: si la cible du projet de démarrage est Any CPUet que vous exécutez sur un système d'exploitation 64 bits, vous perdez la possibilité de modifier et de continuer pendant le débogage. (Vous déboguez efficacement un processus 64 bits). Vous pouvez définir la cible du projet de démarragex86 pour contourner ce problème lors du débogage. (Les assemblys référencés à partir du projet de démarrage peuvent continuer à cibler Any CPU.
Cristian Diaconescu
8
@CristiDiaconescu Avec VS2013 Modifier et continuer est maintenant possible
ms007
Je pense qu'il devrait y avoir une note ici pour savoir si le projet est une application ou une bibliothèque de classes car la définition du nombre cible pour cette dernière peut avoir un impact sur sa disponibilité pour les applications consommatrices en fonction de la plate-forme. Je suis tombé sur cela avec une x86bibliothèque consommée par une AnyCPUapplication où je devais régler Prefer 32-bitpour éviter une erreur de chargement.
SteveCinq

Réponses:

386

Un assembly AnyCPU JIT en code 64 bits lorsqu'il est chargé dans un processus 64 bits et 32 ​​bits lorsqu'il est chargé dans un processus 32 bits.

En limitant le CPU, vous diriez: il y a quelque chose utilisé par l'assemblage (quelque chose qui n'est probablement pas géré) qui nécessite 32 bits ou 64 bits.

AnthonyWJones
la source
3
Alors, comment puis-je produire un assemblage qui sera JIT en x64 en C ++?
galets
50
Les projets C ++ se compilent en code natif, donc le compilateur JIT n'est pas impliqué ... ainsi, vous ne pouvez pas faire ce que vous demandez.
cplotts
7
@cplotts: puisque @galets a posé cette question il y a 3 mois, il est peu probable qu'il verra votre réponse. Utilisez le préfixe @galets dans votre commentaire de la même manière que je l'ai ici pour qu'il reçoive une alerte concernant votre réponse.
AnthonyWJones
4
@AnthonyWJones En général, vous avez raison, sauf lorsque l'utilisateur est l'OP de la question, comme dans ce cas, car ils seront informés de tous les commentaires.
Mark Hurd
12
@MarkHurd En fait, dans ce cas, le PO ne sera pas informé. Les OP ne sont pas informés des commentaires des réponses à moins qu'ils ne soient spécifiquement cinglés avec la syntaxe @. Les OP ne sont automatiquement informés que des commentaires ajoutés à leur question d'origine.
RSW
322

Je pense que la plupart des choses importantes ont été dites, mais je pensais simplement ajouter une chose: si vous compilez en tant que CPU et que vous exécutez sur une plate-forme x64, vous ne pourrez pas charger de fichiers DLL 32 bits, car votre application n'a pas été démarrée dans WoW64 , mais ces fichiers DLL doivent y être exécutés.

Si vous compilez en tant que x86, le système x64 exécutera votre application dans WoW64 et vous pourrez charger des fichiers DLL 32 bits.

Je pense donc que vous devriez choisir "Any CPU" si vos dépendances peuvent fonctionner dans l'un ou l'autre environnement, mais choisissez x86 si vous avez des dépendances 32 bits. Cet article de Microsoft l'explique un peu:

/ CLRIMAGETYPE (spécifier le type d'image CLR)

Soit dit en passant, cette autre documentation Microsoft convient que x86 est généralement un choix plus portable:

Le choix de x86 est généralement la configuration la plus sûre pour un package d'application car il s'exécutera sur presque tous les appareils. Sur certains appareils, un package d'application avec la configuration x86 ne s'exécutera pas, comme la Xbox ou certains appareils IoT Core. Cependant, pour un PC, un package x86 est le choix le plus sûr et a la plus grande portée pour le déploiement de périphériques. Une partie substantielle des appareils Windows 10 continue d'exécuter la version x86 de Windows.

Paul A Jungwirth
la source
2
Vous pouvez peut-être modifier votre réponse pour indiquer comment déterminer si une DLL donnée est de 32 bits uniquement. Pour autant que je sache, cela devrait comprendre cela. Je pense que nous espérons des DLL qui sont également "Any CPU", plutôt que seulement x86.
Dan W
+1 une distinction importante. A dû utiliser une dépendance 32 bits (qui n'a pas été identifiée comme telle). Impossible de comprendre les messages d'erreur d'exécution cryptiques. Sur un pressentiment a changé la cible du processeur et cela a fonctionné, mais est allé chercher "pourquoi". Ce sera bien un jour quand tout sera en 64 bits et que les problèmes d'incompatibilité sembleront étranges comme 16 bits contre 32 bits le sont maintenant.
Gerald Davis
2
@GeraldDavis - Je suis d'accord. L'ironie est qu'il n'y a aucune raison technologique de ne pas pouvoir mélanger les dépendances 32 bits et 64 bits (juste l'absence d'une couche thunking dans le CLR) et j'ai été déçu au début de .NET quand j'ai vu le bit- Ness était toujours quelque chose à considérer lors du déploiement (étant donné qu'il s'agit d'un VM / JIT, cela aurait été l'occasion de fournir un peu plus de valeur ajoutée).
codenheim
1
@mrjoltcola: Pire encore, Microsoft a décidé pour la raison que je ne peux pas imaginer que les entrées de registre devraient être divisées en un univers 32 bits et 64 bits même si elles contrôlent des choses comme les couleurs d'écran, les paramètres par défaut, etc.
supercat
C'est la réponse que je cherchais ... Merci!
Murat de Daminion Software
52

Voici un aperçu rapide qui explique les différentes cibles de construction.

D'après ma propre expérience, si vous cherchez à construire un projet qui fonctionnera sur les plates-formes x86 et x64, et que vous n'avez aucune optimisation x64 spécifique, je changerais la construction pour dire spécifiquement "x86".

La raison en est parfois que vous pouvez obtenir des fichiers DLL qui entrent en collision ou du code qui finit par planter WoW dans l'environnement x64. En spécifiant spécifiquement x86, le système d'exploitation x64 traitera l'application comme une application x86 pure et s'assurera que tout fonctionne correctement.

Dillie-O
la source
37
Ce qui pourrait être terrible si vous écrivez pour un environnement de serveur et souhaitez que votre application puisse utiliser plus de 2 Go de mémoire. Vous désactivez également toutes les optimisations JIT x64 qui pourraient un jour tomber.
Austin Harris
La quantité de problèmes d'exécution que j'ai rencontrés avec les compilations AnyCPU est toute la justification dont j'avais besoin pour cesser de l'utiliser comme option de génération, sauf si quelqu'un a explicitement demandé des binaires qui fonctionnent sur les deux. Je n'ai vu personne demander des binaires x86 sur x64 depuis plus de 10 ans.
kayleeFrye_onDeck
2
"En spécifiant spécifiquement x86, le système d'exploitation x64 traitera l'application comme une application x86 pure et s'assurera que tout fonctionne correctement." - Désolé, je ne suis pas d'accord. Le système d'exploitation x64 exécutera toujours votre application x86 dans un WOW64
Mandeep Janjua
Ce n'est qu'un mauvais conseil pour quelqu'un qui ne comprend pas bien l'impact que cela aura. @AustinHarris donne un excellent exemple. Imaginez un processus de travail Web limité à seulement quelques Go de RAM (j'ai récemment dû gérer cela en production).
rgoliveira
47

Consultez l'article Explication de la cible de la plate-forme Visual Studio .NET .

Le paramètre par défaut, "Any CPU", signifie que l'assembly s'exécutera en mode natif sur le processeur sur lequel il s'exécute actuellement. Cela signifie qu'il s'exécutera en 64 bits sur une machine 64 bits et en 32 bits sur une machine 32 bits. Si l'assembly est appelé à partir d'une application 64 bits, il fonctionnera comme un assembly 64 bits et ainsi de suite.

Le lien ci-dessus a été signalé comme étant rompu, voici donc un autre article avec une explication similaire: ce que AnyCPU signifie vraiment en tant que .NET 4.5 et Visual Studio 11

DCNYAM
la source
1
Lien rompu - accès à un domaine parqué maintenant.
Jon Adams
J'ai ajouté un lien vers un deuxième article avec des informations similaires. J'ai laissé le premier lien au cas où ce domaine serait réactivé.
DCNYAM
46

Crédit au livre "CLR via C #" , voir ceci:

Entrez la description de l'image ici

Ivan
la source
3
Ceci est la réponse la plus précise au 09/06/2018 et VS 15.8.0
Raikol Amaro
39

«N'importe quel processeur» signifie que lorsque le programme est démarré, le .NET Framework déterminera, en fonction du témoin du système d'exploitation, s'il faut exécuter votre programme en 32 bits ou 64 bits.

Il existe une différence entre x86 et Any CPU : sur un système x64, votre exécutable compilé pour X86 fonctionnera comme un exécutable 32 bits.

En ce qui concerne vos soupçons, accédez simplement à la ligne de commande Visual Studio 2008 et exécutez ce qui suit.

dumpbin YourProgram.exe /headers

Il vous dira le témoin de votre programme, et bien plus encore.

AngryHacker
la source
7
S'il est intégré dans "n'importe quel processeur", il apparaîtra comme 32 bits dans les en-têtes de la benne.
Kirbinator
34

Tout processeur signifie qu'il fonctionnera sur n'importe quelle plate-forme. En effet, le code managé est similaire à Java. Considérez-le comme étant compilé en un code d'octet qui est interprété par le .NET Framework au moment de l'exécution.

C ++ n'a pas cette option car il est compilé en code machine spécifique à la plateforme.

Adam Tegen
la source
12
+1 pour avoir répondu à la partie de la question que personne d'autre n'a posée (à propos des projets C ++ n'ayant pas AnyCPU en option).
cplotts
C ++ / CLI peut être compilé en code IL sans aucun code machine (/ clr: pure). Mais sizeof (void *) doit toujours être une constante de compilation en C ++; donc même quand il n'y a pas de code machine impliqué, vous ne pouvez toujours pas créer un binaire qui fonctionnera sur 32 bits et 64 bits en même temps.
Daniel
5

Je recommande de lire ce post .

Lors de l'utilisation d' AnyCPU , la sémantique est la suivante:

  • Si le processus s'exécute sur un système Windows 32 bits, il s'exécute en tant que processus 32 bits. CIL est compilé en code machine x86.
  • Si le processus s'exécute sur un système Windows 64 bits, il s'exécute en tant que processus 32 bits. CIL est compilé en code machine x86.
  • Si le processus s'exécute sur un système ARM Windows, il s'exécute en tant que processus 32 bits. CIL est compilé en code machine ARM.
mamczas
la source
8
Uniquement si "Préférer 32 bits" est sélectionné.
Florian Winter
Quelle est la valeur par défaut depuis Visual Studio 11
Moerwald
@Moerwald Je pense que c'était un bug qui a été corrigé. Si vous lisez le message auquel mamczas fait référence, l'auteur écrit «dans l'interface utilisateur de Visual Studio actuelle« Préférer 32 bits »est grisée et décochée, alors qu'en réalité elle est activée…»; Dans ma version de VS (15.8.0), l'option est toujours grisée et décochée, cependant, elle fonctionne comme prévu (indicateur 32BITPREF = FALSE dans la section CorFlags de l'assembly compilé)
Raikol Amaro