处理 .NET 中的 32 位、64 位和AnyCPU 编译选项






4.70/5 (15投票s)
您是否曾经想过为什么 Visual Studio IDE 提供了 3 种编译选项 - x86、x64 和 Any CPU?在这篇文章中,我希望对此有所阐述。
您是否曾想过 Visual Studio IDE 为什么提供 3 种编译选项 - x86
、x64
和 Any CPU
?
虽然大多数人都知道这些选项,但很多人仍然不清楚这些选项的意义(包括我早期职业生涯中也是如此)。因此,在这篇文章中,我希望能够消除一些疑虑。
Windows 操作系统经历了多年的发展,从最初的 **16 位** 操作系统,过渡到 **32 位**(x86
),再到最近的 **64 位**(x64
)。
为什么要在 32 位之上使用 64 位操作系统?
要理解这一点,让我们先了解 **32 位** 和 **64 位** CPU 的能力。
-
32 位 CPU
- 地址指针大小为 **32 位** -> 可以访问 **2^32 (4,294,967,296)** 个离散地址。
- 这允许程序在内存中创建高达 **4 GB** 大小的数据结构。
-
64 位 CPU
- 地址指针大小为 **64 位** -> 可以访问 **2^64 (18,446,744,073,709,551,616)** 个离散地址。
- 这允许程序在内存中创建高达 **16 EB**(艾字节)大小的数据结构。
-
主要优势(64 位相对于 32 位)
- 与 **32 位** CPU 相比,**64 位** CPU 上的进程可以处理更多的数据集(仅受限于物理内存)。
- 一个 **64 位** 整数进行算术或逻辑运算,使用 **64 位** 类型(如 **C#** 的
long
)比使用两个 **32 位** 操作实现的运算更快。
-
总而言之,在所有实际应用场景下……
- 使用大量内存的应用程序,如图像和视频编辑软件、3D 渲染工具和视频游戏,将能更好地利用 **64 位架构** 和操作系统,特别是当机器拥有 **8 GB** 甚至 **16 GB** 的 **RAM**,并且可以分配给需要它的应用程序时。
理解 32 位、64 位和 Any CPU 编译的 PE 文件行为
-
在 32 位机器上
- **Any CPU**:作为 **32 位** 进程运行,可以加载 **Any CPU** 和
x86
程序集,如果尝试加载x64
程序集,将收到BadImageFormatException
。 - **Any CPU-32 位优先(默认)**:与 **Any CPU** 相同。
- **x86**:与 **Any CPU** 相同。
- **x64**:始终收到
BadImageFormatException
。
- **Any CPU**:作为 **32 位** 进程运行,可以加载 **Any CPU** 和
-
在 64 位机器上
- **Any CPU**:作为 **64 位** 进程运行,可以加载 **Any CPU** 和
x64
程序集,如果尝试加载x86
程序集,将收到BadImageFormatException
。 - **Any CPU-32 位优先(默认)**:作为 **32 位** 进程运行,可以加载 **Any CPU** 和
x86
程序集,如果尝试加载x64
程序集,将收到BadImageFormatException
。 - **x86**:作为 **32 位** 进程运行,可以加载 **Any CPU** 和
x86
程序集,如果尝试加载x64
程序集,将收到BadImageFormatException
。 - **x64**:与 **Any CPU** 相同。
- **Any CPU**:作为 **64 位** 进程运行,可以加载 **Any CPU** 和
Any CPU-32 位优先
这是从 **.NET 4.5** 和 **Visual Studio 11** 开始引入的新选项。它是 **Any CPU** 的一个新子类型,也是 **IDE** 中的默认编译选项。
您可以在项目属性中检查此项,如下图所示…
32 位 PE 在 64 位架构上如何工作?
- 通常,只有 **32 位** PE 可以加载到 **32 位** 进程中,只有 **64 位** PE 可以加载到 **64 位** 进程中。
- 当 **32 位** PE 在 **64 位** 操作系统上运行时,它会在 **“WOW”**(**Windows-32 on Windows-64**)中运行,为进程呈现一个 **32 位** 操作系统的 *假象*。
为什么引入 Any CPU 编译选项?
- 在 **64 位** Windows 操作系统出现之前,只有 **32 位** PE(当然,我们在此讨论中不考虑 **16 位** 操作系统),因此在编译时,这些 PE 被标记为 **32 位**,没有歧义。
- 随着 **64 位** Windows 操作系统的引入,必须做出一个决定——默认情况下,二进制文件应该被标记为 **32 位** 还是 **64 位**?
- 从技术上讲,托管二进制文件没有 *硬 CPU 依赖性* - 它们可以是 **32 位** 或 **64 位**。
- 但是,需要一种方法来让 **32 位** 和 **64 位** 进程重用 .NET 库。为此,**OS 加载器** 的支持得到了扩展,以支持 **体系结构中立** 的 PE 文件 **(Any CPU)**。
- 对于 **Any CPU** PE,**OS 加载器** 决定如何初始化进程。在 **64 位** 操作系统上,它们作为 **64 位** 进程运行;在 **32 位** 操作系统上,它们作为 **32 位** 进程运行。
希望这篇文章有助于澄清一些事情!!
我将在未来的文章中介绍如何识别 PE 的 **体系结构亲和性**。
缩写
- **PE**:进程可执行文件(EXEs 和 DLLs)
参考文献
- 截至 .NET 4.5 和 Visual Studio 11,AnyCPU 真正意味着什么
- AnyCPU EXEs 通常比它们有价值时更麻烦
- 问答 - 64 位处理器的优点是什么?
- 问答 - C# 是为 32/64 位编译,还是为 Any CPU 编译?
- 问答 - Visual Studio 的“Any CPU”目标是什么意思?
文章 处理 .NET 中的 32 位、64 位和 Any CPU 编译选项 首次出现在 Sundeep Kamath 的博客。