关键字:托管代码managed code, 不安全代码unsafe code, 固定托管指针fixed, 在stack上分配空间stackalloc
Managedd Code和UnManaged Code
运行在公共语言运行库 (CLR) 的控制之下的代码称为“托管代码”,运行在 CLR 之外的代码称为“非托管代码”。COM、COM+、C++ 组件、ActiveX 组件和 Win32 API 都是非托管代码的示例。
概念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 是指向未知类型的指针 |