轉 C 託管記憶體與非託管記憶體之間的轉換

2021-09-05 06:49:24 字數 1970 閱讀 7038

1.c#的託管**和非託管**

c#有自己的記憶體**機制,所以在c#中我們可以只new,不用關心怎樣delete,c#使用gc來清理記憶體,這部分記憶體就是managed memory,大部分時候我們工作於c#環境中,都是在使用託管記憶體,然而c#畢竟執行在c++之上,有的時候,(比如可能我們需要引入一些第三方的c++或native**的庫,在unity3d開發中很常見)我們需要直接在c#中操縱非託管的**,這些non-managed memory我們就需要自己去處理他們的申請和釋放了, c# 中提供了一些介面,完成託管和非託管之間的轉換,以及對這部分記憶體的操作。基本上有以下幾種:

2.managed mem-> un-managed mem

比如在c#中呼叫第三方的某個c++庫,庫中有個函式是void func(float * data, int length).我們需要傳入給data的就應該是乙個非託管的**(why?首先傳入託管的記憶體,c#層很可能會把它gc掉,而c++還在使用,而且託管的mem它的指標位址可能會發生改變,因此直接傳給c++可能拿到的位址是錯誤的)

**如下:

using system.runtime.interopservices;

float _managed_data  =... // this is the c# managed data

gchandle unmanaged_data_handle = gchandle.alloc(_managed_data, gchandletype.pinned); //這裡將標記_managed_data暫時不能被gc**,並且固定物件的位址

func(unmanaged_data_handle.addrofpinnedobject(),_managed_data.length);//這裡將拿到非託管記憶體的固定位址,傳給c++

unmanaged_data_handle.free();//使用完畢後,將其handle free,這樣c#可以正常gc這塊記憶體

3.un-managed mem->managed mem, 在c++中返回乙個un-managed mem給c#使用

有時需要在c++中分配一塊處理好的記憶體,然後返回給c#來使用,如c++中某個介面 int func(int** data) (注意這裡要使用指標的指標,因為data是得到的結果)

intptr unmanaged_ptr=intptr.zero; //定義這個c#中用來接收c++返回資料的指標型別

int length = func(out unmanaged_ptr );//呼叫c++的函式,使unmanaged_ptr指向c++裡分配的記憶體,注意這裡用out ,才能與c++裡面的**匹配。

byte managed_data = new byte[length];

marshal.copy(unmanaged_ptr, managed_data, 0, length);//將非託管記憶體拷貝成託管記憶體,才能在c#裡面使用

marshal.freehglobal(unmanaged_ptr);//釋放非託管的記憶體

4.在c#直接申請乙個un-managed mem傳給c++

有時需要直接在c#開闢一塊非託管的記憶體,傳給c++用,這塊記憶體同樣可以在c#中用後銷毀。**如下

intptr unmanaged_data_prt = marshal. allochglobal(100);// 直接分配100 byte的記憶體

func(unmanaged_data_prt);//傳給c++使用

marshal.freehglobal(unmanaged_data_prt);使用後銷毀非託管記憶體

此外 marshal類裡面還有很多處理非託管記憶體的方法。

託管記憶體和非託管內存在c#裡面可以互相自由的轉化,主要通過marshal類和gchandle類,程式設計時只要注意非託管的記憶體一定要負責好釋放就可以了。

--------------------- 

原文: 

C 託管記憶體與非託管記憶體之間的轉換

c 有自己的記憶體 機制,所以在c 中我們可以只new,不用關心怎樣delete,c 使用gc來清理記憶體,這部分記憶體就是managed memory,大部分時候我們工作於c 環境中,都是在使用託管記憶體,然而c 畢竟執行在c 之上,有的時候,比如可能我們需要引入一些第三方的c 或native 的...

c 關於非託管記憶體的釋放問題

硬體 大華sdk 軟體平台 win10 vs2015 背景 近期在做大華工業相機sdk的採集的時候,用到marshal.copy,將託管的 轉換成非託管的指標記憶體,由於沒有及時釋放記憶體指標,導致pc的記憶體一直 通過檢視 之後發現是因為記憶體指標的原因,所以使用 marshal.freehglo...

python轉C的記憶體洩露問題

python的記憶體管理是引用機制,然後如果變數的引用數不減的話,那麼即使使用記憶體 也是然並卵的效果。python轉c的擴充套件的時候,c是可以對python的引用機制進行人為增減的,所以就導致可能的記憶體洩露。使用swig等工具模板,可能能夠避免手工忘記的一些問題,但是,如果你原來的 仍然是存在...