關鍵字:Managed 程式碼managed code, 不安全的程式碼unsafe code, 固定託管指標fixed, 在stack上分配空間stackalloc
Managedd Code和UnManaged Code
運行在公用語言運行庫 (CLR) 的控制之下的代碼稱為“Managed 程式碼”,運行在 CLR 之外的代碼稱為“Unmanaged 程式碼”。COM、COM+、C++ 組件、ActiveX 組件和 Win32 API 都是Unmanaged 程式碼的樣本。
概念1:安全的程式碼safe code和不安全的程式碼unsafe code的概念
所謂安全的程式碼,是指由CLR進行託管並進行安全性驗證的代碼。在安全的程式碼中,我們無法進行記憶體的直接操作,因為所有記憶體heap是託管堆(managed heap)。 但是有些應用中,仍然需要對記憶體的直接操作,這時候就需要將代碼標記為不安全的程式碼unsafe。
不安全的程式碼就是無法通過CLR進行安全驗證的代碼,其安全性由自己負責保證代碼不會引起安全風險或指標錯誤。
凡是需要操作指標的代碼都必須標記為非安全的程式碼。
不安全的程式碼的關鍵字為unsafe.
注意:在 C# 中,為了編譯不安全的程式碼,必須用 /unsafe 編譯應用程式。
概念2:fixed關鍵字的應用
在託管架構下,我們知道,所有reference type的instance在託管heap中的地址不是固定的,他們要隨著GC的不斷回收記憶體,託管對象也要在generational Garbage Collector 0,1,2之間移動。那麼如果我們編寫不安全的程式碼,如何用指標指向某個託管對象呢?
唯一的方法就是:將託管堆中的該對象固定住!這就是我們的關鍵字fixed。也就是要將所要指向的託管對象固定住。
如
int[] a=new int[10];
unsafe
{
fixed(int *p=a) //將a 固定住!
{
對指標p進行操作......
}
}
概念3:在堆棧上動態分配空間 stackalloc
在unsafe context下,我們可以在stack上動態分配記憶體塊。因為該申請到的記憶體塊不屬於託管堆,不會受到GC的制約,記憶體塊的生存期受定義它的方法的生存期的限制。因此,該記憶體塊不需要被固定住(fixed)
例如:
public unsafe void Test
{
int *p=stackalloc int[100];
/*
在stack(注意:不是managed heap!!切記)上申請了一段長100個整數的數組,p指向該數組的首地址。
*/
int [] q=new int [100];
/*
q就是在managed heap上申請的空間,如果此時有一個指標指向q,就必須將其固定住
fixed(int *p1=q)
{
}
*/
}
概念4:C#中的各種指標類型
樣本 |
說明 |
int* p |
p 是指向整數的指標 |
int** p |
p 是指向整數的指標的指標 |
int*[] p |
p 是指向整數的指標的一維數組 |
char* p |
p 是指向字元的指標 |
void* p |
p 是指向未知類型的指標 |