xan*_*tos 31
这取决于.你使用free和delete释放用malloc和分配的内存new.
但
一般来说,如果你进行PInvoke调用,那么指针应该是a IntPtr.
如果使用fixed(或GCHandle)获取托管对象的指针,则从GC内存分配内存
fixed块或释放该内存GCHandle)时,GC将返回处理它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
Run Code Online (Sandbox Code Playgroud)
或者,几乎相当(但安全性稍差,因为取消固定是手动完成的)
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
Run Code Online (Sandbox Code Playgroud)
通过使用Marshal.AllocCoTaskMem(注意Marshal.AllocCoTaskMem调用CoTaskMemAllocWindows API,因此您可以使用它们Marshal.FreeCoTaskMem和Windows API CoTaskMemFree来释放它)从"本机"池(通过COM对象通常使用的分配器)分配一些内存的示例:
// 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);
Run Code Online (Sandbox Code Playgroud)
或者支持的另一个分配器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);
Run Code Online (Sandbox Code Playgroud)
假设您有一些本机代码,可以访问存储一些数据的内存:
static extern IntPtr GetSomeMemoryFromSomeWinApi();
static extern void FreeSomeMemoryFromSomeWinApi(IntPtr ptr);
Run Code Online (Sandbox Code Playgroud)
你这样使用:
IntPtr p5 = GetSomeMemoryFromSomeWinApi();
// here you have some memory received from some native API
// and here you free it
FreeSomeMemoryFromSomeWinApi(p5);
Run Code Online (Sandbox Code Playgroud)
在这种情况下,你的库必须给你一个Free方法,因为你不知道如何分配内存,但有时你的库的文档告诉你内存是通过一个特定的分配器分配的,所以你使用那种类型的deallocator像它一样释放它
Marshal.FreeCoTaskMem(p5);
Run Code Online (Sandbox Code Playgroud)
如果API是某个COM对象.
该Marshal班甚至有分配器BSTR(由COM对象使用Unicode字符串.他们有自己的长度预系列吊灯)
string str = "Hello";
char *bstr = (char*)Marshal.StringToBSTR(str);
Marshal.FreeBSTR((IntPtr)bstr);
Run Code Online (Sandbox Code Playgroud)
他们有特殊处理,因为他们的"真正的"起始地址就像(bstr - 2)(他们有一个Int32长度的前缀)
关键在于分配器的数量与沙漠的沙粒和天空的星星一样多.它们中的每一个(除了标准的.NET之一,使用的那个new)都有一个相应的解除分配器.他们像丈夫和妻子一样.他们不与他人混在一起.
最后一点,如果你写混合.NET /本地C或C++代码,你就不得不暴露调用一些C/C++方法的 free/delete,因为他们的free/ delete是其C不是的OS/C++库的一部分, .