为什么.net程序集对于不同的架构有所不同?

时间:2010-02-20 10:02:17

标签: .net x86 64-bit

我可以为x86和x64构建我的C#项目。为什么?我认为它生成的特殊代码根本不是特定于平台的。

4 个答案:

答案 0 :(得分:21)

首先,让我直言不讳地说我不知道​​这里的整个故事,我会回答我认为我知道的事情。如果有人能告诉我哪里错了,我会很乐意删除或更改我的答案。

我理解它的方式,这个设置是一个标志,表示“程序集应该在这种类型的体系结构中运行”。这是针对x86和x64设置的。 MSIL / .NET设置只是说“我不在乎,我可以运行,所以选择一个最佳或可用的。”

例如,您可能正在通过P / Invoke调用Win32 API函数,在这种情况下,程序集将无法在x64上运行,您应将其标记为x86。

因此,如果我的理解是正确的,那么这三个标志如何在不同的平台上运行程序集(注意,它是主程序集,程序集,它决定了这一点,而不是每个单独的程序集):

Setting        x86      x64  <-- Platform (CPU/OS)
MSIL/.NET     32-bit   64-bit
x86           32-bit   32-bit
x64           N/A (*)  64-bit

x86上的x64程序集的N / A意味着程序集将不会加载,如果你尝试,你会得到一个例外。

另请注意,涉及x86和x64的冲突设置会使您的程序在某个时刻崩溃。如果主程序集设置为x86,它将在32位和64位操作系统上作为32位进程运行,并且加载标记为x64的程序集的任何尝试都将失败。同样,如果主程序集设置为x64,它将仅在64位操作系统上运行,并且任何将程序集设置为x86的尝试都将失败。

MSIL主可执行程序集将在32位操作系统上以32位运行(如果它设置为x86,具有上述故障点),并在64位操作系统上以64位运行(就像它设置为x64一样,具有上述故障点。)

显然通常情况下,如果你没有调用被标记为特定内容的程序集,并且只要你没有进行P / Invoke,那么你想要使用MSIL设置。 t可移植到32位和64位(我不知道这是否有效,如果P / Invoke到win-api函数将映射到正确的位数化dll。)

由于引用是指针,并且指针在两个平台上存储为本机x位地址,具体取决于您拥有的引用数量,可能有一个案例反对使用MSIL 。但是,在更改设置之前,您应该验证这是一个问题。

答案 1 :(得分:3)

该标志对EXE文件很重要。它决定您是在32位还是64位进程中运行。如果您使用.NET代码中的“本机”DLL,则需要遵循这些DLL的体系结构。

EXE文件中的“Any CPU”将选择x64(如果可用)。

答案 2 :(得分:3)

首先,在64位版本的Windows上调试项目时,在.exe项目上将Platform Target设置为x86非常有用。 VS2005 / 8调试器不支持64位代码上的Edit + Continue。

如果您的程序依赖于仅在32位代码中运行的组件,那么您应该在发布版本中选择x86。这并不罕见,有大量的COM组件从未有过,永远不会被移植到64位非托管代码。一个典型的例子是Microsoft Jet数据库引擎。

选择x64是非常不寻常的,没有太多的非托管代码只能在64位版本中使用。值得注意的是,在构建程序集时会收到警告,有几个.NET框架程序集包含非托管代码;在c:\ windows \ microsoft.net中只能使用它们的32位版本。您可以安全地忽略这些警告,64位版本实际安装在GAC中。

选择x64时的一个问题是,C#3.0编译器会发出一个二进制文件,要求Windows创建一个4兆字节堆栈大小的启动线程,而不是默认的1兆字节。这有点合理,64位代码确实需要更多堆栈来存储指针并返回地址。

最后,Windows SDK具有Corflags.exe工具,可用于在构建后切换程序集的位。 / 32BIT +选项相当于将Platform Target设置为x86。使用/ 32BIT-可确保程序集在64位操作系统上以64位模式运行。使用Editbin.exe工具可以更改默认堆栈大小。

答案 3 :(得分:1)

我认为存在不同目标的原因是由于标量类型的大小。我认为它也会影响处理COM对象的方式。

我遇到的情况是我有第三方.NET库,如果在64位应用程序中使用,程序在调用库时会失败,因此我必须限制为仅32位模式。