zoukankan      html  css  js  c++  java
  • 【转】托管代码和非托管代码的区别

    什么是托管代码(managed code)?

          托管代码是一microsoft的中间语言(IL),他主要的作用是在.NET   FRAMEWORK的公共语言运行库(CLR)执行代码前去编译源代码,也就是说托管代码充当着翻译的作用,源代码在运行时分为两个阶段:       1.源代码编译为托管代码,(所以源代码可以有很多种,如VB,C#,J#)       2.托管代码编译为microsoft的平台专用语言。

          编译器把代码编译成中间语言(IL),而不是能直接在你的电脑上运行的机器码。中间语言被封装在一个叫程序集(assembly)的文件中,程序集中包含了描述你所创建的类,方法和属性(例如安全需求)的所有元数据。你可以拷贝这个程序集到另一台服务器上部署它。

          托管代码在公共语言运行库(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平台的其他编程语言不一样,Visual C++可以创建非托管程序。当你创建一个项目,并且选择名字以M FC,ATL或者Win32开头的项目类型,那么这个项目所产生的就是非托管程序。

    区别:

         1、托管代码是一种中间语言,运行在CLR上;

              非托管代码被编译为机器码,运行在机器上。

         2、托管代码独立于平台和语言,能更好的实现不同语言平台之间的兼容;

              非托管代码依赖于平台和语言。

         3、托管代码可享受CLR提供的服务(如安全检测、垃圾回收等),不需要自己完成这些操作;

              非托管代码需要自己提供安全检测、垃圾回收等操作。

          托管代码就意味着托管数据?答案是否定的。

          对于Visual Basic和C#来说,生活是简单的,因为你没有其它选择。当你在那些语言里面声明一个类,那么这个类的实例会在托管堆中被创建,垃圾收集器(GC)会帮我们管理这些对象的回收。但是在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关键字。这个关键字会给代码带来巨大的区别。

          托管类型是可以被垃圾回收器所回收的。他们必须要用关键字new来创建,永远都不会在栈中出现。所以下面这行代码是合法的:

          Foo f;

          但是这一行代码就是非法的:

          Bar b;

          如果我在堆中创建一个Foo对象,那么我必须要负责清理这个对象:

          Foo* pf = new Foo(2);       // . . .       delete pf;

          C++编译器实际上会用两个堆,一个托管堆和一个非托管堆,然后通过对new操作符的重载来实现对创建不同类型类的实例,分配不同的内存。如果我在堆里面创建一个Bar实例,那么我可以忽略它。当没有其他代码在使用它的时候,垃圾回收器会自动清理这个类,释放其占用的资源。 对于托管类型会有一些约束:它们不能实现多重继承,或者继承于非托管类型;它们不能用friend关键字来实现私有访问,它们不能实现拷贝构造函数。所以,你有可能不想把你的类声明为托管类型。但是这并不意味着你不想让你的代码成为托管代码。在Visual C++中,你可以选择。

          托管代码与非托管代码的性能比较       基本上每个人都知道的是,所有.Net语言都将被编译成为一个叫做IL汇编的中间语言。但是计算机是如何执行这个中间代码的,却是很多人不知道,甚至理解错误了的。       JIT是.NET程序运行的重要部件之一,全称是即时编译器。很多人(绝对不是少数,问了很多c++程序员,10个有9个这种想法)都以为JIT其实就是跟Java VM差不多的东西,是一个Interpreter,在运行时读取IL汇编代码,然后模拟成x86代码(也就是俗称的虚拟机)。但是事实上,.NET使用的是更为高级的技术。 .Net程序被加载入内存以后,当某段IL代码被第一次运行的时候,JIT编译器就会将这段IL代码,全部编译成本地代码,然后再执行。这也就是为什么.NET程序第一次运行都启动很慢的原因! 随.NET库,微软还附带了一个工具,可以事先将.NET程序所有的IL代码都编译成本地代码并保存在缓存区中,这样一来,这个程序就跟c++编译的一模一样了,没有任何区别,运行时也可以脱离JIT了(这里不要混淆了,这里不是说可以脱离.NET库,而是说不需要在进行即时编译这个过程了)。所以,请不要将.NET和Java混为一谈,两个的运行效率根本不是一个等级的!

         JIT的优化指的是可以针对本地CPU,在编译时进行优化。传统程序在编译时,为了保证兼容性,通常使用最通用的指令集(比如古老的386指令集)来编译。而JIT知道CPU的具体类型,可以充分利用这些附加指令集进行编译,这样的性能提升是很可观的。

  • 相关阅读:
    Photoshop 基础七 位图 矢量图 栅格化
    Photoshop 基础六 图层
    Warfare And Logistics UVALive
    Walk Through the Forest UVA
    Airport Express UVA
    Guess UVALive
    Play on Words UVA
    The Necklace UVA
    Food Delivery ZOJ
    Brackets Sequence POJ
  • 原文地址:https://www.cnblogs.com/lionwang/p/6803005.html
Copyright © 2011-2022 走看看