http://www.codeguru.com/Csharp/.NET/cpp_managed/article.php/c4871

本文内容

  • 什么是托管代码?
  • 什么是非托管代码?
  • 什么是本地代码?
  • 托管代码意味着托管数据?

虽然该文章写的时间比较早,但是完全可以说明问题。

2003 年 4 月 24 日 VS 2003(之前称为 Everett)发布,很多开发者愿意考虑使用托管代码的新技术。但是对这个新技术有点迷茫,特别是 C++ 开发者。因为,正如我之前指出的,C++ 是特殊的。

什么是托管代码(Managed Code)?


托管代码是 Visual Basic .NET 和 C# 编译器创建。它们编译成中间语言(IL),而不是直接在计算机上运行的机器代码。IL 被保存在一个称为程序集中,以及描述代码的类、方法、和属性(如安全性要求)的元数据文件。在 .NET 里,程序集是“一站式(one-stop-shopping)”部署的单元。可以将程序集直接复制到另一台服务器上进行部署。

托管代码运行在公共语言运行库(Common Language Runtime,CLR)。CLR 为正在运行的代码提供多种服务。在通常代码事件中,它首先加载和验证程序集,确保 IL 正确。然后,当程序集运行,方法被调用时,CLR 安排它们被编译为适合机器的机器码,并缓存该机器码,以便下次被调用时使用。这被称为 Just In Time,或 JIT compiling,或简称 Jitting。

当程序集运行时,CLR 继续提供诸如安全、内存管理、线程和其他的服务。应用程序是由 CLR 来管理的。

Visual Basic .NET 和 C# 只能产生托管代码。如果你用的是这些应用程序,那么你就正在使用托管代码。Visual C ++ .NET 也能产生托管代码,就是当你创建一个项目,选择名为“.Managed”开始的应用程序类型,如“.Managed C++ application”。

什么是非托管代码(Unmanaged Code)?


非托管代码是你以前用 Visual Studio .NET 2002 创建的代码。现在你还有很多 Visual Basic 6、Visual C ++ 6,甚至是使用了 15 年的老 C 编译器产生的非托管代码。非托管代码直接被编译成机器码,跟你具有相同或几乎相同的芯片的机器上都能运行。但是,它不能从不可见的运行时里获得诸如安全或内存管理等服务,而只能从操作系统获得,通过调用 Windows SDK 提供的 API。最近,有越来越多的非托管应用程序通过 COM 调用获得操作系统的服务。

不同于 Visual Studio 2003 中的其他语言,Visual C ++ 可以创建非托管应用程序。当你创建一个项目,选择以 MFC、ATL 或 Win32 开头的应用程序,就创建了一个非托管的应用程序。

这导致一些混淆,也就是说,当创建一个托管的 C++ 应用程序时,那么生成结果是一个 .exe 扩展名的 IL 装配文件。当你创建一个 MFC 应用程序,生成结果是一个本地代码(native code)的 Windows 可执行文件,扩展名也是 .exe。这两个文件的内部布局完全不同。你可以使用中间语言反汇编工具(Intermediate Language Disassembler)ildasm,查看内部装配,以及元数据文件和 IL。在非托管的 .exe 文件使用 ildasm,你会被告知没有有效的 CLR 头,不能反汇编——虽然扩展名相同,但文件完全不同。

什么是本地代码(Native Code)?


本地代码在两种情况下使用。许多人把非托管代码作为本地代码的同义词:用旧的编译工具或是 Visual C ++ 生成代码,不会运行在 CLR 上,而是在计算机本地。这可能是一个完整的应用,也可能是一个 COM 组件或通过 COM Interop 或 PInvoke 由托管代码调用的 DLL。COM Interop 和 PInvoke 是强大的工具,确保,当你将旧代码移动到新环境时,仍然可以使用。我更喜欢说非托管代码。从这个意义上,因为它强调的是代码不会得到运行时的服务。例如,托管代码中代码访问安全性(Code Access Security),会阻止代码从另一个服务装载代码,防止破坏性的行为。如果你的应用程序从另一个服务加载非托管代码,就无法得到这种保护。

本地代码的另一个使用是描述了 JIT 编译器的输出,机器代码事实上是运行在运行时上。这是托管的,不是 IL,而是机器码。因此,不能假设本地代码等同于非托管代码。

托管代码意味着托管数据?


对于 Visual Basic 和 C#,生存期问题很简单,因为你别无选择。当你声明一个类,在托管堆上创建该类的实例,而垃圾回收器关心该实例的生存期问题。但是在 Visual C++,你是有选择的。即使你创建一个托管应用程序,也可以由你决定类是否是一个托管类型或一个非托管类型。

下面是一个非托管类型:

class Foo

{

    private:

        int x;

    public:

        Foo(): x(0){}

        Foo(int xx): x(xx) {}

};

下面是一个托管类型:

__gc class Bar

{

    private:

        int x;

    public:

        Bar(): x(0){}

        Bar(int xx): x(xx) {}

};

唯一的区别是Bar定义前边的 __gc 关键字,但却有很大不同。关于 __gc 关键字参见MSDN:ms-help://MS.VSCC.v90/MS.MSDNQTR.v90.chs/dv_fxintro/html/6a1f9b6c-9983-4722-8b58-13e9af2a1339.htm

托管类型是可以被回收的。它们必须用new来创建,不在堆上。因此,下面是对的:

Foo f;

但下面是不允许的:

Bar b;

如果我必须在堆上创建Foo的一个实例,那一定要记着清除它:

Foo* pf = new Foo(2);

// . . .

delete pf;

在C ++编译器实际上使用两个堆,一个是托管的,一个是非托管的,使用重载的new操作符,当创建用一个new创建实例时,来确定分配的内存在哪里。如果在堆上创建Bar的一个实例,那么可以忽略它。垃圾回收器将会回收它。在 Visual C++,你是有选择的。

.NET 托管、非托管、本地:这些代码有什么区别?的更多相关文章

  1. 托管非托管Dll动态调用

    原文:托管非托管Dll动态调用 最近经常看到有人问托管非托管Dll调用的问题.对于动态库的调用其实很简单.网上很多代码都实现了Dll的静态调用方法.我主要谈论下动态库的动态加载. 对于托管动态库,实现 ...

  2. .Net 程序在自定义位置查找托管/非托管 dll 的几种方法

    原文:.Net 程序在自定义位置查找托管/非托管 dll 的几种方法 一.自定义托管 dll 程序集的查找位置 目前(.Net4.7)能用的有2种: #define DEFAULT_IMPLEMENT ...

  3. C# 托管非托管资源释放

    1.C#几乎所有对象都为托管对象,不同点是有的对象封装了非托管资源. 2.C#大部分对象在进行垃圾回收时都可以回收,包括非托管资源,因为非托管资源都已经通过C#类进行了封装,会将非托管资源的释放放在析 ...

  4. C#的托管与非托管大难点

    托管代码与非托管代码 众所周知,我们正常编程所用的高级语言,是无法被计算机识别的.需要先将高级语言翻译为机器语言,才能被机器理解和运行.在标准C/C++中,编译过程是这样的:源代码首先经过预处理器,对 ...

  5. C#的三大难点之二:托管与非托管

    相关文章: C#的三大难点之前传:什么时候应该使用C#?​C#的三大难点之一:byte与char,string与StringBuilderC#的三大难点之二:托管与非托管C#的三大难点之三:消息与事件 ...

  6. 编写高质量代码改善C#程序的157个建议——建议50:在Dispose模式中应区别对待托管资源和非托管资源

    建议50:在Dispose模式中应区别对待托管资源和非托管资源 真正资源释放代码的那个虚方法是带一个bool参数的,带这个参数,是因为我们在资源释放时要区别对待托管资源和非托管资源. 提供给调用者调用 ...

  7. 重学c#系列——c# 托管和非托管资源与代码相关(四)

    前言 这是续第三节. 概况垃圾回收与我们写代码的关系: 强引用和弱引用 针对共享 Web 承载优化 垃圾回收和性能 应用程序域资源监视 正文 强引用和弱引用 垃圾回收器不能回收仍在引用的对象的内存-- ...

  8. C# 托管和非托管混合编程

    在非托管模块中实现你比较重要的算法,然后通过 CLR 的平台互操作,来使托管代码调用它,这样程序仍然能够正常工作,但对非托管的本地代码进行反编译,就很困难.   最直接的实现托管与非托管编程的方法就是 ...

  9. 斗地主你什么时候才会托管?(.NET中的托管于非托管)

    文章部分引自<.NET4.0面向对象编程漫谈(基础篇)>第1章.NET面向对象编程基础(作者:金旭亮) 无意间看到一位四五岁左右小朋友在玩斗地主,总开始到结束,她一直都在使用“提示”(托管 ...

随机推荐

  1. 使用EF Code First搭建一个简易ASP.NET MVC网站,允许数据库迁移

    本篇使用EF Code First搭建一个简易ASP.NET MVC 4网站,并允许数据库迁移. 创建一个ASP.NET MVC 4 网站. 在Models文件夹内创建Person类. public ...

  2. ios 向sqlite数据库插入和读取图片数据

    向sqlite数据库插入和读取图片数据 (for ios) 假定数据库中存在表 test_table(name,image), 下面代码将图片文件test.png的二进制数据写到sqlite数据库: ...

  3. eval json ajax

    在JS中将JSON的字符串解析成JSON数据格式,一般有两种方式: 1.一种为使用eval()函数. 2. 使用Function对象来进行返回解析. 使用eval函数来解析,并且使用jquery的ea ...

  4. SqlServer 查看备份文件中逻辑文件信息的Sql语句

    RESTORE FILELISTONLY FROM DISK = 'D:\All\DataBase\(2013-12-18)-1.bak' 用来查看备份文件中的逻辑文件信息. 相关信息:SqlServ ...

  5. Android工具类 DateUtil,可以用它方便的进行日期的操作

    本文转载自:http://blog.csdn.net/xuduzhoud/article/details/27526177 全部代码如下: DateUtil.java package com.exam ...

  6. VS Code搭建.NetCore开发环境(一)

    一.使用命令创建并运行.Net Core程序 1.dotnet new  xxx:创建指定类型的项目console,mvc,webapi 等 2.dotnet restore :加载依赖项 dotne ...

  7. Generalized normal distribution and Skew normal distribution

    Density Function The Generalized Gaussian density has the following form: where  (rho) is the " ...

  8. Django的事务性

    Django默认是自动提交的 使用TestCase的每个test用例都是事务性的.如果不想这样,可以使用TransactionTestCase 替代 Django自动保证delete()/update ...

  9. 【BZOJ】【3930】【CQOI2015】选数

    数论/莫比乌斯反演/快速mu前缀和 比较容易想到令f[x]表示gcd=x的方案数,令g[x]表示x|gcd的方案数. 那么有$ g(d)=\sum_{d|n} f(n)$,根据莫比乌斯反演,有$f(d ...

  10. 从客户端(SeekingJobs="<B>·</B> 物流规划,<B>·</...")中检测到有潜在危险的 Request.Form 值。

    今天提交各东西发觉出错了,错误信息如下: “/”应用程序中的服务器错误. 从客户端(SeekingJobs="<B>·</B> 物流规划,<B>·< ...