.NET 托管、非托管、本地:这些代码有什么区别?
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 托管、非托管、本地:这些代码有什么区别?的更多相关文章
- 托管非托管Dll动态调用
原文:托管非托管Dll动态调用 最近经常看到有人问托管非托管Dll调用的问题.对于动态库的调用其实很简单.网上很多代码都实现了Dll的静态调用方法.我主要谈论下动态库的动态加载. 对于托管动态库,实现 ...
- .Net 程序在自定义位置查找托管/非托管 dll 的几种方法
原文:.Net 程序在自定义位置查找托管/非托管 dll 的几种方法 一.自定义托管 dll 程序集的查找位置 目前(.Net4.7)能用的有2种: #define DEFAULT_IMPLEMENT ...
- C# 托管非托管资源释放
1.C#几乎所有对象都为托管对象,不同点是有的对象封装了非托管资源. 2.C#大部分对象在进行垃圾回收时都可以回收,包括非托管资源,因为非托管资源都已经通过C#类进行了封装,会将非托管资源的释放放在析 ...
- C#的托管与非托管大难点
托管代码与非托管代码 众所周知,我们正常编程所用的高级语言,是无法被计算机识别的.需要先将高级语言翻译为机器语言,才能被机器理解和运行.在标准C/C++中,编译过程是这样的:源代码首先经过预处理器,对 ...
- C#的三大难点之二:托管与非托管
相关文章: C#的三大难点之前传:什么时候应该使用C#?C#的三大难点之一:byte与char,string与StringBuilderC#的三大难点之二:托管与非托管C#的三大难点之三:消息与事件 ...
- 编写高质量代码改善C#程序的157个建议——建议50:在Dispose模式中应区别对待托管资源和非托管资源
建议50:在Dispose模式中应区别对待托管资源和非托管资源 真正资源释放代码的那个虚方法是带一个bool参数的,带这个参数,是因为我们在资源释放时要区别对待托管资源和非托管资源. 提供给调用者调用 ...
- 重学c#系列——c# 托管和非托管资源与代码相关(四)
前言 这是续第三节. 概况垃圾回收与我们写代码的关系: 强引用和弱引用 针对共享 Web 承载优化 垃圾回收和性能 应用程序域资源监视 正文 强引用和弱引用 垃圾回收器不能回收仍在引用的对象的内存-- ...
- C# 托管和非托管混合编程
在非托管模块中实现你比较重要的算法,然后通过 CLR 的平台互操作,来使托管代码调用它,这样程序仍然能够正常工作,但对非托管的本地代码进行反编译,就很困难. 最直接的实现托管与非托管编程的方法就是 ...
- 斗地主你什么时候才会托管?(.NET中的托管于非托管)
文章部分引自<.NET4.0面向对象编程漫谈(基础篇)>第1章.NET面向对象编程基础(作者:金旭亮) 无意间看到一位四五岁左右小朋友在玩斗地主,总开始到结束,她一直都在使用“提示”(托管 ...
随机推荐
- Spring Cloud Gateway服务网关
原文:https://www.cnblogs.com/ityouknow/p/10141740.html Spring 官方最终还是按捺不住推出了自己的网关组件:Spring Cloud Gatewa ...
- Occlusion Culling遮挡剔除理解设置和地形优化应用
这里使用的是unity5.5版本 具体解释网上都有,就不多说了,这里主要说明怎么使用,以及参数设置和实际注意点 在大场景地形的优化上,但也不是随便烘焙就能降低帧率的,必须结合实际情况来考虑,当然还有透 ...
- 真爱如血第七季/全集True Blood迅雷下载
第七季 True Blood Season 7(2014)看点:由于日本科学家合成了一种人造血,一夜之间,吸血鬼不再是人们心中那富有传奇色彩的怪物,而是能与人类和平相处的朋友.已经播出五年的HBO吸血 ...
- 《Google Glass开发指南》
<Google Glass开发指南> 基本信息 作者: BestApp工作室 丛书名: 图灵原创 出版社:人民邮电出版社 ISBN:9787115349477 上架时间:2014-3-19 ...
- JAVA基础知识之编译、运行、打包
一:java环境设置在环境变量中设置以下三个变量: JAVA_HOME=C:\j2sdk1.4.1 //可以改为相应的目录CLASSPATH=%JAVA_HOME%\lib\tools.jar;%JA ...
- Django静态文件的加载以及STATIC_URL、 STATIC_ROOT 、STATICFILES_DIRS的区别
Djangon生产环境静态资源的处理 Django 关闭DEBUG模式后,就相当于是生产环境了. Django框架一旦作为生产环境,它的静态文件访问接口就不应该从Django框架中走,必须在Djang ...
- 【keytool jarsigner工具的使用】Android 使用JDK1.7的工具 进行APK文件的签名,以及keystore文件的使用
一个android apk的编译过程 请参考: http://www.2cto.com/kf/201312/261475.html 典型的编译过程: aapt( Android Asset Packa ...
- iOS:viewController 和 view 的生命周期、不错的代码设计风格
一.介绍: viwe和viewController的生命周期是最基本的知识,如果很好地理解它们的方法调用的执行顺序,就能很好地设计代码的风格.这篇博客转载自:http://www.cnblogs.co ...
- uva 331 Mapping the Swaps 求交换排序的map 纯DFS
给出一个序列,每次交换两个数,求有几种交换方法能使序列变成升序. n不大于5,用dfs做. 代码: #include <cstdio> #include <cstring> # ...
- 聊聊jdbc statement的fetchSize
在使用MySQL的JDBC时,如果查询结果集过大,使用一次查询,可能会出现Java.lang.OutOfMemoryError: Java heap space问题,因为DB服务器端一次将查询到的结果 ...