删除C#不安全指针

我知道在C#中使用/unsafe标志,你可以使用指针。 在C / C ++中删除指针你会使用free(pointer);delete pointer; 分别。 但是,如何使用C#指针实现相同的效果?

这取决于。 你使用freedelete来释放用mallocnew分配的malloc

一般来说,如果你进行PInvoke调用,那么指针应该是一个IntPtr

如果使用fixed (或GCHandle )获取托管对象的指针,则从GC内存分配内存

  • 对于GC的内存,当您取消固定该内存(退出fixed块或释放GCHandle )时,GC将返回处理它
  • 对于通过.NET Marshal方法分配的内存,您可以使用补充的Free方法
  • 对于从本机方法接收的内存,您必须使用“正确的”本机方法来释放它。

固定内存的内存示例:

 int[] arr = new int[5]; fixed (int* p = arr) { // here arr is fixed in place and it won't be freed/moved by gc } // here arr is un-fixed and the GC will manage it 

或者,几乎相当(但安全性稍差,因为取消固定是手动完成的)

 GCHandle handle = GCHandle.Alloc(arr, GCHandleType.Pinned); int* p2 = (int*)handle.AddrOfPinnedObject(); // here arr is fixed in place and it won't be freed/moved by gc handle.Free(); // here arr is un-fixed and the GC will manage it 

通过使用Marshal.AllocCoTaskMem从“本机”池(通过COM对象通常使用的分配器)分配一些内存的示例(请注意, Marshal.AllocCoTaskMem调用Windows API的CoTaskMemAlloc ,因此您可以同时使用Marshal.FreeCoTaskMem和Windows API CoTaskMemFree释放它):

 // allocating space for 1000 chars char* p3 = (char*)Marshal.AllocCoTaskMem(1000 * sizeof(char)); // here you can use p3 // and here you free it Marshal.FreeCoTaskMem((IntPtr)p3); 

或者使用Marshal支持的另一个分配器(这是Windows API通常使用的分配器):

 // allocating space for 1000 chars char* p4 = (char*)Marshal.AllocHGlobal(1000 * sizeof(char)); // here you can use p4 // and here you free it Marshal.FreeHGlobal((IntPtr)p4); 

假设你有一些Native代码可以让你访问一些保存一些数据的内存:

 static extern IntPtr GetSomeMemoryFromSomeWinApi(); static extern void FreeSomeMemoryFromSomeWinApi(IntPtr ptr); 

你这样使用:

 IntPtr p5 = GetSomeMemoryFromSomeWinApi(); // here you have some memory received from some native API // and here you free it FreeSomeMemoryFromSomeWinApi(p5); 

在这种情况下,你的库必须给你一个Free方法,因为你不知道内存是如何分配的,但有时你的库的文档告诉你内存是通过一个特定的分配器分配的,所以你使用那种类型的解除分配器以释放它,就像

 Marshal.FreeCoTaskMem(p5); 

如果API是某个COM对象。

Marshal类甚至还有BSTR的分配器(COM对象使用的Unicode字符串。它们的长度为前端)

 string str = "Hello"; char *bstr = (char*)Marshal.StringToBSTR(str); Marshal.FreeBSTR((IntPtr)bstr); 

他们有特殊处理,因为他们的“真实”起始地址就像(bstr – 2)(他们有一个Int32前置长度)

关键在于分配器的数量与沙漠的沙粒和天空的星星一样多。 它们中的每一个(除了标准的.NET之外, new使用的那个)都有一个相应的解除分配器。 他们像丈夫和妻子一样。 他们不与他人混在一起。

最后要注意的是,如果你编写混合的.NET /本机C或C ++代码,你将不得不公开一些调用它们的 free / delete C / C ++方法,因为它们的free / delete是它们的C / C ++库的一部分,不是操作系统。