在编写托管代码的过程中,往往需要利用非托管内存的简单分配删除的特性,例如想生成一个大对象,使用之后想马上释放,就很适合在非托管内存中建立这个大对象。建立后,在托管代码中,需要一个句柄能指向这个大对象的内存,如下图所示。
这个过程可以使用Marshal类的AllocHGlobal方法,这个方法使用 GlobalAlloc 从进程的非托管内存中分配内存,并操作非托管内存。
Marshal::AlloclHGlobal()

相反,我们有时也希望在托管内存中分配内存,并在本地内存的指针指向它。例如在编写托管代码时,需要使用原来的库函数。但是托管代码所分配的内存都在托管堆中,本地堆中的指针不能直接指向它,如上图所示。
这时可以使用GCHandle的Alloc方法,这个方法为指定的对象分配句柄。所支持的句柄有:
![]() |
Normal
|
此句柄类型表示不透明句柄,这意味着无法通过此句柄解析固定对象的地址。可以使用此类型跟踪对象,并防止它被垃圾回收器回收。当非托管客户端持有对托管对象的唯一引用(从垃圾回收器检测不到该引用)时,此枚举成员很有用。
|
![]() |
Pinned
|
此句柄类型类似于 Normal,但允许使用固定对象的地址。这将防止垃圾回收器移动对象,因此将降低垃圾回收器的效率。使用
Free方法可尽快释放已分配的句柄。
|
![]() |
Weak
|
此句柄类型用于跟踪对象,但允许回收该对象。当回收某个对象时,GCHandle 的内容归零。在终结器运行之前,Weak 引用归零,因此即使终结器使该对象复活,Weak 引用仍然是归零的。
|
![]() |
WeakTrackResurrection
|
该句柄类型类似于 Weak,但如果对象在终结过程中复活,此句柄不归零。
|
其中Pinned句柄就是pin_ptr,由于该内存地址不变,所以该句柄指向的托管内存不进行垃圾回收,可以与指针相互转换。



下面代码使用vs2005的C++/CLI语言进行了试验。首先新建两个数组,并对第一俄数组进行赋值,将该数组转化为指针后,调用IPP的图像处理操作,镜像操作。然后将结果保存在第二个数组中。最后将两个数组显示出来。





































在Form1_Paint()方法中绘制两个Bitmap:



