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


71

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

这是C#代码时,如何在C#中编写的代码不被托管,以及如何使大小的内存变为非托管。一个例子和一点见识会有所帮助。


Answers:


150

简短答案:

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

长答案:

什么是托管代码?

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

托管代码在公共语言运行时中运行。运行时为正在运行的代码提供各种服务。在正常情况下,它将首先加载并验证程序集,以确保CIL正常。然后,在调用方法时,运行时将运行时安排它们编译为适合运行程序集的机器的机器代码,并缓存该机器代码以在下次调用该方法时使用。(这称为“及时”或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。

来源


我仍然对托管和非托管数据类型感到困惑。它们是否存在于当前的.net框架中。
拉詹·米什拉

8

这可能是一个很长的答案,谈论C编译器生成的机器代码与JIT编译器从托管程序生成的机器代码之间的许多细微差别。足够长的时间才能真正需要一本书,但是这种书已经写好了。例如,杰弗里·里希特(Jeffrey Richter)所做的任何事情。

我将使它简短而活泼,因为所有这些细微的差异都归结为一个规则:

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



1

通常,托管代码比编写良好的非托管(本机)代码具有更高的运行时内存占用量。


其示出了差bettwen托管和未托管代码的任何示例
Simsons

难以量化,您的里程会有所不同:)。但是托管代码需要开销。例如 运行时能够跟踪JIT状态,垃圾收集,对象必须具有可用于反射,等等,等等元数据
seand

所以我将要知道我在写什么是托管代码还是非托管代码
Simsons,2010年

1

非托管代码:-

1.该代码是在.NET Framework外部开发的,称为非托管代码。

2.不在CLR控制下运行的应用程序被称为不受管理的,某些语言(例如C ++)可用于编写此类应用程序,例如,这些应用程序访问操作系统的底层功能。与VB,ASP和COM代码的后台兼容性是非托管代码的示例。

3.非托管代码在包装类的帮助下执行。

4.包装器类有两种类型:CCW(COM可调用包装器)和RCW(运行时可调用包装器)。

5.Wrapper用于在CCW和RCW的帮助下弥补差异。托管代码应用程序域中的资源就是托管代码。域内的资源更快。

托管代码 1.在.NET框架中开发的代码称为托管代码。该代码由CLR在托管代码执行的帮助下直接执行。.NET Framework中编写的任何语言都是托管代码。

2.托管代码使用CLR,CLR依次通过管理内存,处理安全性,允许跨语言调试等来管理您的应用程序。


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.