ChatGPT解决这个技术问题 Extra ChatGPT

Visual Studio“任何 CPU”目标是什么意思?

我对 Visual Studio 2008 中的 .NET 平台构建选项有些困惑。

什么是“Any CPU”编译目标,它生成什么样的文件?我检查了这个“任何 CPU”构建的输出可执行文件,发现它们是 x86 可执行文件(谁不会看到它的到来!)。那么,将可执行文件定位到 x86 与“任何 CPU”之间有什么区别吗?

我注意到的另一件事是托管 C++ 项目没有此平台作为选项。这是为什么?这是否意味着我对“任何 CPU”可执行文件是普通的 32 位可执行文件的怀疑是正确的?

在决定使用哪个平台目标时要考虑的另一件事:如果 Startup project 的目标是 Any CPU 并且您在 64 位操作系统上运行,您将失去 的能力在调试时编辑并继续。 (您正在有效地调试 64 位进程)。您可以将 Startup project 设为目标 x86 以在调试时规避此问题。 (从启动项目引用的程序集可能会继续以 Any CPU 为目标。
@CristiDiaconescu 现在可以使用 VS2013 编辑并继续
我认为这里应该注意项目是应用程序还是类库,因为为后者设置目标位数可能会影响其对使用应用程序的可用性,具体取决于平台。我在一个 AnyCPU 应用程序使用 x86 库时遇到了这个问题,我必须设置 Prefer 32-bit 以避免加载错误。

P
Peter Mortensen

AnyCPU 程序集在加载到 64 位进程时将 JIT 到 64 位代码,当加载到 32 位进程时将 JIT 到 32 位代码。

通过限制 CPU,您会说:程序集使用的某些东西(可能是非托管的)需要 32 位或 64 位。


那么,如何在 C++ 中生成将 JIT 转换为 x64 的程序集?
C++ 项目编译为本机代码,因此不涉及 JIT 编译器……因此,您不能按照您的要求进行操作。
此链接上来自 MS 的一些信息:msdn.microsoft.com/en-us/library/zekwfyz4.aspx
嗨,安东尼,请更新您的答案 the 32-bit preferred optionThis answerthis answer 包含最新信息。
这个答案不再正确。多年来,AnyCPU 的含义发生了数次变化。
P
Peter Mortensen

我想大部分重要的东西已经说了,但我只是想补充一点:如果你编译为 Any CPU 并在 x64 平台上运行,那么你将无法加载 32 位 DLL 文件,因为您的应用程序不是在 WoW64 中启动的,但那些 DLL 文件需要在那里运行。

如果您编译为 x86,则 x64 系统将在 WoW64 中运行您的应用程序,您将能够加载 32 位 DLL 文件。

因此,如果您的依赖项可以在任一环境中运行,我认为您应该选择“Any CPU”,但如果您有 32 位依赖项,请选择 x86。 Microsoft 的这篇文章对此进行了一些解释:

/CLRIMAGETYPE (Specify Type of CLR Image)

顺便说一句,this other Microsoft documentation 同意 x86 通常是更便携的选择:

选择 x86 通常是应用程序包最安全的配置,因为它几乎可以在所有设备上运行。在某些设备上,具有 x86 配置的应用程序包将无法运行,例如 Xbox 或某些 IoT Core 设备。但是,对于 PC,x86 包是最安全的选择,并且具有最大的设备部署范围。很大一部分 Windows 10 设备继续运行 x86 版本的 Windows。


也许您可以编辑您的答案,说明如何确定给定的 DLL 是否仅为 32 位。据我所知,this 应该解决这个问题。我认为我们希望 DLL 也是“任何 CPU”,而不仅仅是 x86。
+1 一个重要的区别。需要使用 32 位依赖项(未确定为这样)。无法弄清楚神秘的运行时错误消息。预感改变了 cpu 目标并且它工作但去寻找“为什么”。当一切都是 64 位并且不兼容问题看起来像现在的 16 位和 32 位一样古怪时,总有一天会很好。
@GeraldDavis - 我同意。具有讽刺意味的是,没有技术原因不能混合 32 位和 64 位依赖项(只是 CLR 中缺少一个 thunking 层),当我在 .NET 的早期看到 bit-在部署时仍然需要考虑 ness (考虑到这是一个 VM / JIT,这将是一个提供更多附加值的机会)。
@mrjoltcola:比这更糟糕的是微软决定的方式,因为我无法理解注册表项应该分为 32 位和 64 位宇宙,即使它们控制屏幕颜色、默认设置等。
这是我正在寻找的答案...谢谢!
P
Peter Mortensen

感谢这本书"CLR via C#",请参阅:

https://i.stack.imgur.com/xzfCG.png


这是截至 09/06/2018 和 VS 15.8.0 的最准确答案
P
Peter Mortensen

下面是解释不同构建目标的 a quick overview

根据我自己的经验,如果您希望构建一个可以在 x86 和 x64 平台上运行的项目,并且您没有任何特定的 x64 优化,我会将构建更改为专门说“x86”。

造成这种情况的原因是有时您可能会在 x64 环境中获得一些冲突的 DLL 文件或导致崩溃 WoW 的一些代码。通过专门指定 x86,x64 操作系统会将应用程序视为纯 x86 应用程序,并确保一切顺利运行。


如果您为服务器环境编写并希望您的应用程序能够使用超过 2GB 的内存,这可能会很糟糕。您还可以选择退出任何有朝一日可能会出现的 x64 JIT 优化。
我在 AnyCPU 编译中遇到的大量运行时问题是我停止使用它作为构建选项所需的全部理由,除非有人明确要求在两者上都可以使用的二进制文件。 10 多年来,我没有人要求 x64 上的 x86 二进制文件。
“通过专门指定 x86,x64 操作系统会将应用程序视为纯 x86 应用程序,并确保一切运行顺利。” - 对不起,我不同意。 x64 操作系统仍将在 WOW64 中运行您的 x86 应用程序
对于那些不完全了解它会产生的影响的人来说,这只是一个糟糕的建议。 @AustinHarris 举了一个很好的例子。想象一个仅限于几 GB RAM 的 Web Worker 进程(我最近不得不在生产中处理这个问题)。
W
Wai Ha Lee

查看文章Visual Studio .NET Platform Target Explained

默认设置“任何 CPU”意味着程序集将在当前运行的 CPU 上本地运行。意思是,它将在 64 位机器上以 64 位运行,在 32 位机器上以 32 位运行。如果从 64 位应用程序调用程序集,它将作为 64 位程序集执行,依此类推。

上面的链接已经被报坏了,所以这里有另一篇类似解释的文章:What AnyCPU Really Means As Of .NET 4.5 and Visual Studio 11


P
Peter Mortensen

“Any CPU”是指当程序启动时,.NET Framework 会根据操作系统的位数来确定是以 32 位还是 64 位运行您的程序。

x86 和 Any CPU 之间存在区别:在 x64 系统上,为 X86 编译的可执行文件将作为 32 位可执行文件运行。

就您的怀疑而言,只需转到 Visual Studio 2008 命令行并运行以下命令。

dumpbin YourProgram.exe /headers

它将告诉您程序的位数,以及更多信息。


如果它内置在“任何 cpu”中,它将在 dumpbin 标头中显示为 32 位。
A
Adam Tegen

任何 CPU 意味着它可以在任何平台上工作。这是因为托管代码类似于 Java。将其视为被编译为 .NET Framework 在运行时解释的字节码。

C++ 没有此选项,因为它被编译为特定于平台的机器代码。


+1 用于回答其他人没有做过的问题的一部分(关于没有 AnyCPU 作为选项的 C++ 项目)。
C++/CLI 可以编译为 IL 代码,无需任何机器代码 (/clr:pure)。但是 sizeof(void*) 在 C++ 中仍然需要是编译时常量;因此,即使不涉及机器代码,您仍然无法创建同时适用于 32 位和 64 位的二进制文件。
P
Peter Mortensen

我推荐阅读this post

使用 AnyCPU 时,语义如下:

如果进程在 32 位 Windows 系统上运行,则它作为 32 位进程运行。 CIL 被编译成 x86 机器码。如果进程在 64 位 Windows 系统上运行,则它作为 32 位进程运行。 CIL 被编译成 x86 机器码。如果进程在 ARM Windows 系统上运行,它将作为 32 位进程运行。 CIL 被编译为 ARM 机器代码。


只有选择“优先32位”。
这是自 Visual Studio 11 以来的默认设置
@Moerwald 我相信这是一个已修复的错误。如果您阅读了 post mamczas 所引用的内容,作者写道“在当前的 Visual Studio UI 中,“首选 32 位”已灰显且未选中,实际上它已启用……”;在我的 VS (15.8.0) 版本中,该选项仍然显示为灰色且未选中,但是,它可以按预期工作(已编译程序集的 CorFlags 部分中的标志 32BITPREF = FALSE)