了解.Net中的32位与64位

And*_*ens 4 .net c# 32bit-64bit

我总是绕过构建64位桌面应用程序的问题,因为我不知何故在我脑海里发现这不是一件容易的事情,而且我想我并不是真的理解解决方案"配置管理器"对话框,平台和配置.

无论如何,我只是尝试通过简单地将所有解决方案项目的平台更改为x64来转换现有应用程序,并且它有效.我唯一的问题是其中一个项目引用的C++ DLL,需要重建为x64.

所以我的问题(最后)是:为什么我只有C++ DLL的问题,但我的解决方案中的项目引用的许多.Net程序集DLL都没问题?

究竟是什么决定了我的应用程序是否构建为64位?我将所有解决方案的项目更改为"x64",但如果将它们保留为"任何CPU",它是否仍然有用,我只将WPF(启动)项目更改为"x64"?

编辑

所以最后我似乎只能将所有项目平台设置为"任何CPU"而不是"x64"(TFS服务器无法使用后者运行单元测试).甚至引用非托管64位DLL的项目也很满意(不确定原因).

诀窍是取消选中Prefer 32-bitWPF(启动)项目属性中的选项.构建的应用程序现在作为64位应用程序运行,并且TFS /单元测试运行愉快.

Mat*_*har 7

TL;DR:.Net 程序集永远不会被组装成机器特定的指令,而是被编译成在 .Net 虚拟机下运行的 MSIL,在运行时,VM 使用 JITer 生成可由 CPU 执行的机器指令。


32bit和64bit那个“破坏”目标文件之间的区别是:指针大小、内存模型和最重要的指令集架构(ISA)。让我们分解每一点,看看为什么.Net程序集大多不受影响。

点大小(或长度)

在32bit执行环境中,指针是 32 位长,正如您所期望的 int 64 位,它们是 64 位长。这一事实可以通过以下两种方式之一破坏您的程序集:

  1. 如果包含指针的结构需要更多(或更少)字节来存储指针,则它们的内部内存结构将发生变化。
  2. 指针算术——一些聪明的开发人员喜欢玩弄指针,屏蔽它们,添加它们等等。在某些情况下,指针的大小可能是这些计算的整数,以产生正确的结果。

为什么 .Net 程序集不受影响

由于 .Net 语言是safe- 您无法使用指针(通常,除非您处于不安全的环境中)。没有使用指针的选项解决了第二点。至于第一点 - 这就是您可以获得类的大小(使用sizeof)而不是包含类引用的结构的大小的原因。

内存模型

旧的32bit处理器曾经有一个功能叫Memory segmentation允许OS或 aSupervisor program声明使用特殊CPU registers调用访问的内存区域Segment registers。在64bit这个功能中大多是禁用的。因此,编译为在内存分段下工作的程序在非分段环境中可能会出现问题。

为什么 .Net 程序集不受影响

通常我们不会在这么低的级别处理内存,这是可能的,因为正.Net virtual machine如下一点所解释的那样。

指令集架构

32bit和64bit(x86和AMD64) 相似但完全不同ISAs,这意味着在一个下运行的代码将不会在另一个下运行。因此,与其他两点不同,无论您在其中写了什么,这一点都会破坏您的程序集。

为什么 .Net 程序集不受影响

那么 .Net 程序集怎么可能被编译为Any CPU?诀窍在于,当您编译 .Net 语言时,您永远不会组装它。这意味着当您按下时,compile您只会将代码编译成未组装(即未通过汇编程序运行)的中间对象(称为 .Net 程序集)。

通常,当您在其中编译代码时,C/++首先通过 compile 运行它assembly instructions,然后生成一些这些指令,然后将其传递给assembler生成machine instructions. CPU 只能执行这些machine instructions。

.Net 语言是不同的,如上所述,当您编译 .Net 语言时,您通过编译器运行它并停在那里,不涉及汇编程序。此处的 compile 也会生成一些assembler instructions指令,但与compile 生成的指令不同,c/c++这些指令与机器无关,它们是用称为MSIL - Microsoft intermediate language. 没有 CPU 知道如何执行这些指令,因为就像普通的汇编指令一样,它们也必须组装成机器指令。

诀窍是这一切都发生在运行时,当用户打开你的程序时,他启动了一个.Net runtime运行你的程序的实例,你的程序永远不会直接针对本地机器本身运行。当您的程序需要调用一个方法时,.Net 虚拟机中的一个特殊组件称为 .Net 虚拟机的JITer - just in time compiler任务是将这个方法从 MSIL 组装到特定于安装了 .Net 框架的机器的机器指令。


And*_*ers 5

从正确性的角度来看,32/64仅在您与本机代码进行互操作,使用低级不安全功能或分配大量(> 4GB)内存时才有意义.如果不考虑这些因素,您可以使用AnyCpu.AnyCpu代码将默认为您的主机操作系统位数(尽管可以更改默认值),因此对于大多数人来说,它最终将以64位进程运行.

有时性能原因显然需要32或64位.32位应用程序通常会更加缓存友好.计算绑定应用程序在以64位进程运行时应该表现更好(尽管并非总是如此).