1. 程式人生 > >【轉】托管代碼和非托管代碼的區別

【轉】托管代碼和非托管代碼的區別

產生 沒有 匯編代碼 cati 一行 包含 虛擬機 被調用 庫類

什麽是托管代碼(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的具體類型,可以充分利用這些附加指令集進行編譯,這樣的性能提升是很可觀的。

【轉】托管代碼和非托管代碼的區別