托管代码和非托管代码,内存和大小有什么区别?

Sim*_*ons 69 .net c# unmanaged managed

在看到和听取很多关于托管和非托管代码之后,并且知道唯一的区别是托管是关于CLR而非托管是在CLR之外,这让我非常好奇地了解它.它是什么,托管和非托管代码,内存和大小?

我在C#中编写的代码如何是非托管的,而这是C#代码,以及大小的内存如何变得不受管理.一个例子和一点点见解会有所帮助.

Shi*_*mmy 146

简短回答:

  • 托管代码是您编写并编译为.NET CIL的 .NET代码(VB.NET,C#等).
  • 非托管代码是不在.NET下编译为直接机器代码的代码.

答案很长:

什么是托管代码?

托管代码是Visual Basic .NET和C#编译器创建的代码.它编译为中间语言(IL),而不是编译可以直接在您的计算机上运行的代码.CIL保存在一个名为程序集的文件中,同时还包含描述您创建的代码的类,方法和属性(如安全性要求)的元数据.这个程序集是.NET世界中部署的一站式购物单元.您将其复制到另一台服务器以在那里部署程序集 - 通常复制是部署中唯一需要的步骤.

托管代码在公共语言运行时中运行.运行时为运行的代码提供各种服务.在通常的事件过程中,它首先加载并验证程序集以确保CIL正常.然后,就在调用方法时,运行时会安排将它们编译为适合运行程序集的机器的机器代码,并缓存此机器代码以在下次调用方法时使用.(这称为Just In Time,或JIT编译,或者通常只是Jitting.)

随着程序集的运行,运行时继续提供诸如安全性,内存管理,线程等服务.应用程序由运行时管理.

Visual Basic .NET和C#只能生成托管代码.如果您正在使用这些应用程序,那么您正在制作托管代码.如果您愿意,Visual C++ .NET可以生成托管代码:创建项目时,选择名称以.Managed.开头的应用程序类型之一,例如.Managed C++应用程序.

什么是非托管代码?

非托管代码是您在Visual Studio .NET 2002发布之前使用的代码.Visual Basic 6,Visual C++ 6,哎呀,即使是15年前的C编译器,你可能仍然在你的硬盘驱动器上所有产生的非托管代码.它直接编译为在您编译它的机器上运行的机器代码,并且只要它们具有相同的芯片或几乎相同,就可以在其他机器上编译.它没有从不可见的运行时获得安全性或内存管理等服务; 它从操作系统中获取它们.而且重要的是,它通过调用Windows SDK中提供的API,通过询问它们来明确地从操作系统中获取它们.最近的非托管应用程序通过COM调用获得了操作系统服务.

与Visual Studio中的其他Microsoft语言不同,Visual C++可以创建非托管应用程序.当您创建项目并选择名称以MFC,ATL或Win32开头的应用程序类型时,您将创建一个非托管应用程序.

这可能会导致一些混淆:当您创建.Managed C++应用程序时,构建产品是具有.exe扩展名的CIL程序集.创建MFC应用程序时,构建产品是本机代码的Windows可执行文件,也具有.exe扩展名.两个文件的内部布局完全不同.您可以使用中间语言反汇编程序ildasm查看程序集内部并查看元数据和CIL.尝试将ildasm指向一个非托管的exe,你会被告知它没有有效的CLR(公共语言运行时)标头,并且不能被反汇编 - 相同的扩展名,完全不同的文件.

本地代码怎么样?

短语本机代码用于两个上下文中.许多人将它用作非托管代码的同义词:使用旧工具构建的代码,或在Visual C++中故意选择的代码,它不在运行时运行,而是在机器上本机运行.这可能是一个完整的应用程序,或者它可能是使用COM Interop或PInvoke从托管代码调用的COM组件或DLL,这两个强大的工具可确保您在迁移到新世界时可以使用旧代码.我更喜欢说.unmanaged代码.对于这个含义,因为它强调代码不能获得运行时的服务.例如,托管代码中的代码访问安全性可防止从其他服务器加载的代码执行某些破坏性操作.如果您的应用程序调用从另一台服务器加载的非托管代码,您将无法获得该保护.

短语本机代码的另一个用途是描述JIT编译器的输出,即在运行时实际运行的机器代码.它是管理的,但它不是CIL,它是机器代码.因此,不要只假设native = unmanaged.

(来源)


Han*_*ant 7

这可能是一个非常长的答案,讨论C编译器生成的机器代码与JIT编译器从托管程序生成的机器代码之间的许多细微差别.足够长,真的需要一本书,但这些书已经写好了.杰弗里里希特的任何东西.

我会保持简短和活泼,因为所有这些微妙的差异归结为一个规则:

托管代码是从垃圾收集堆中分配内存的代码.