天天看點

.NET簡談互操作(四:基礎知識之Dispose非托管記憶體)

1.在.NET托管平台上的對象與非托管的對象之間是否能直接互換?

2.托管記憶體與非托管記憶體是否存在差異?如果存在差異是否有方法能進行等價轉換或者叫做等價複制;

我們就上面兩個問題來詳細分析一下,由于本人也在學習這方面的知識是以了解的也不是很透徹,隻能是一些微薄的猜測吧,大家一起來幫忙分析;

第一個問題:在.NET托管平台上的對象與非托管的對象之間是否能直接互換?其實第一個問題是隐藏在第二個問題裡面的,首先我們要确定的是,“互換”與“轉換”的概念,為了統一大家步伐,我們必須将“互換”與“轉換”做一些定義;

“互換”:我假定有兩塊記憶體空間,每塊記憶體空間存儲不同的對象,比如:在一塊非托管記憶體塊中儲存着Char*類型的指針,在另一塊托管記憶體塊中儲存着String類型的值,由于Char*是指針類型,而我們的托管String是.NET平台類型,微小的變化就可能引起記憶體布局不同的可能;資料結構裡面講到,變量分為原子型和結構型,原子型變量都存在着字面值的概念,什麼叫字面值就是我們人用來交流的資料值,比如:bool類型的true和false;兩塊記憶體中儲存的東西是不一樣的,進階語言在經曆了一系列編譯器處理之後,會确定下來記憶體中儲存的資料是什麼樣子的;也就是說記憶體的配置設定原則是按照對象的類型來的;在托管與非托管的記憶體空間中,不同的平台所有的引用位址類型也各不相同,當然如果能成功的“互換”就說明能在托管與非托管之間進行直接資料通路了;總之互換是兩個對象之間的彼此轉換,是雙向的;

“轉換”:轉換的概念我個人覺得來源于進階語言的文法解釋而已,所謂轉換其實也就是a到b的轉換,将一種類型轉換成另一種類型的動詞描述,我們具體點打個比方:如果有一個對象是a,有一個對象是b,我想将a轉換成b,就是将對象從一種狀态轉換成另一種狀态;總之轉換是單向的,隻能是一種到另一種的轉換;

針對上述我們分析的結果,由于時間比較緊,我們從第二個問題入手吧,因為本篇文章不是解決問題為主的;經過上面的分析我們确定托管記憶體與非托管記憶體的結構是不一樣的,這種不一樣并不是所有的對象類型都不一樣,在.NET平台裡面有一些如:int,char之類的平台等價類型,是可以直接互換的;如果是一些非等價類型,要想成功進行轉換就必須得借助于托管對象關于互操作方面的知識了,由于這樣一扯可能今天這篇文章是講不完了,這裡就粗略的過一下吧;我們下面進入今天的主題;其實有些概念真的不太好講,你要說托管與非托管記憶體不一樣,有人會問不一樣在什麼地方;真的沒有說服性的理由;

關于非托管記憶體釋放的問題

.NET平台的預設記憶體配置設定和回收都是基于COM(元件對象模型)的,由于COM是一套非托管年代的公用原則,是以微軟隻能做到這個位置了;如果非托管記憶體是用COM的CoTaskMemAlloc配置設定的那麼.NET的封送拆收器會自動的釋放掉那塊記憶體;如果是非托管記憶體是采用C的或者C++或者其他的什麼方式配置設定的.NET根本不知道你是怎麼配置設定的,是以這個時候需要我們采用折中的辦法來解決。非托管的記憶體釋放隻有非托管知道,是以在非托管中定義一個釋放非托管資源的方法,然後在用.NET平台去調用這個非托管方法來進行釋放記憶體;下面我們來看一個小例子,以說明問題為主;

圖1:

.NET簡談互操作(四:基礎知識之Dispose非托管記憶體)

這是非托管的代碼,由于時間關系我就沒有寫具體的操作了;說明原理就行了;

圖2:

.NET簡談互操作(四:基礎知識之Dispose非托管記憶體)

這是在托管.NET平台上面定義的非托管代碼調用關系;

圖3:

.NET簡談互操作(四:基礎知識之Dispose非托管記憶體)

繼續閱讀