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. Cocos2d-x3.0下实现循环列表

    本文的实现是參照我之前在做iOS时实现的一个能够循环的列表这里用C++重写一遍. 效果: 原文地址:http://blog.csdn.net/qqmcy/article/details/2739301 ...

  2. delphi 实现文件上传下载

    unit UpDownFile; interface uses Windows, Classes, Idhttp, URLMon, IdMultipartFormData; const UpUrl = ...

  3. javascript:常用数组操作

    concat()方法 数组和数组的 粘结: var a=[1,2,3,4]; var b=[5,6,7,8]; var c=a.concat(b); console.log(c); // [1,2,3 ...

  4. 咏南中间件开始支持redis client接口调用

    咏南中间件开始支持redis client接口调用 咏南中间件封装了redis client接口,可以支持REDIS了. 如下图,将数据集写入REDIS缓存,和从REDIS缓存获取数据: proced ...

  5. tms mqtt

    tms mqtt 功能概述 MQTT客户端组件 可用于VCL,FMX和LCL应用 支持Windows,iOS,Android,macOS,Linux,Raspberry Pi 实现完整的MQTT规范, ...

  6. 【Devops】【docker】【CI/CD】关于jenkins构建成功后一步,执行的shell命令详解+jenkins容器运行宿主机shell命令的实现方法

    1.展示这段shell命令 +详解 #================================================================================= ...

  7. dwz 分页 bug (选回 combox 第一个值时不执行 onchange)

    先看一下官方的测试: 官方的演示有两个 bug 一个是combox数字一直不变,二是当选回第一个值时不执行 onchange 事件. 经过firebug调试,这是一个bug,传到后台的参数没有得到及时 ...

  8. 获取客户端网卡MAC地址和IP地址实现JS代码

    获取客户端网卡MAC地址和IP地址实现JS代码 作者: 字体:[增加 减小] 类型:转载   获取客户端的一些信息,如IP和MAC,以结合身份验证,相信很多人都会这样做吧,我们这里用Javascrip ...

  9. Asp.Net Core WebAPI入门整理(四)参数获取

    一.总结整理,本实例对应.Net Core 2.0版本 1.在.Net Core WebAPI 中对于参数的获取及自动赋值,沿用了Asp.Net  MVC的有点,既可以单个指定多个参数,右可以指定Mo ...

  10. MongoDB单机, 主从, 分布式部署

    MongoDB是最易用的NoSQL,比较适合取代MySQL做一些存储,不过不是强一致性的.本文介绍一下MongoDB各种部署方式,并分享一些感受.前两部分“单机部署”和“主从部署”是“分片部署”的基础 ...