问题描述
我知道使用 /不安全
标记在C#中,你可以使用指针。在C / C ++删除指针,你可以使用免费(指针);
和删除指针;
分别。但是,您将如何实现与C#指针同样的效果?
I know using the /unsafe
flag in C#, you can use pointers. In C/C++ to delete a pointer you would use free(pointer);
and delete pointer;
respectively. However, how would you achieve the same effect with the C# pointers?
推荐答案
这要看情况。您可以使用免费
和删除
来的malloc 分配的可用内存和
新
。
It depends. You use
free
and delete
to free memory allocated with malloc
and new
.
但是
在一般的,如果你做一个PInvoke的呼叫,然后指针应该是
的IntPtr
。
in general if you do a PInvoke call, then the pointer should be a
IntPtr
.
如果您使用
固定
(或的GCHandle
),以获得一个指针的管理对象,则内存从GC内存分配
if you use
fixed
(or GCHandle
) to obtain a pointer for a managed object, then the memory was allocated from the GC memory
对于GC的记忆,当你未引脚内存(退出
固定
块,或释放的GCHandle
),GC将返回处理它对于内存通过.NET分配使用的互补
免费
方法元帅
方法对于内存从本机方法获得,你必须使用正确的本地方法来释放它。
For the memory of GC, when you un-pin that memory (exit the
fixed
block, or release theGCHandle
), the GC will return handling itFor memory allocated through .NET
Marshal
methods you use the complementaryFree
methodFor memory received from native methods, you have to use the "correct" native method to free it.
由.NET收到寄托内存的例子:
Example of pinning memory received by the .NET:
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
,或几乎相等(但有点不太安全,因为拔除是手工完成的)
or, nearly equivalent (but a little less safe, because the unpinning is done manually)
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
使用分配从本土池(通过通常使用的COM对象分配器)内存的一些示例
Marshal.AllocCoTaskMem
(注意, Marshal.AllocCoTaskMem
要求的Windows CoTaskMemAlloc来
的API,这样你就可以同时使用 Marshal.FreeCoTaskMem
和Windows API CoTaskMemFree
来释放它):
Example of allocating some memory from the "native" pool (through the allocator normally used by COM objects) by using
Marshal.AllocCoTaskMem
(note that Marshal.AllocCoTaskMem
calls the CoTaskMemAlloc
of Windows API, so you can use both Marshal.FreeCoTaskMem
and the Windows API CoTaskMemFree
to free it):
// 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);
或与
元帅
支持的另一个分配器(这通常是由Windows API的):
or with another allocator supported by
Marshal
(this is the one normally used by 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);
让我们假设你有一些本地的code,让你获得一些内存它可以节省一些数据:
Let's say you have some Native code that gives you access to some memory where it saves some data:
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);
在这种情况下,这是您的图书馆,有给你一个
免费
方法,因为你不知道内存是如何分配的,但有时你的库的文档会告诉你该内存是通过一个特定的分配器分配,使您在使用这种类型的释放器来释放它,就像
In this case it's your library that has to give you a
Free
method, because you don't know how the memory was allocated, but sometimes your library's documentation tells you that the memory is allocated through a specific allocator, so you use that type of deallocator to free it, like
Marshal.FreeCoTaskMem(p5);
如果这个API是一些COM对象。
if the API was some COM object.
在
元帅
类甚至有分配器的 BSTR
(使用COM对象统一code字符串。他们有他们的长度pre-吊灯)
The
Marshal
class even has the allocator for BSTR
(Unicode strings used by COM objects. They have their length pre-pendend)
string str = "Hello";
char *bstr = (char*)Marshal.StringToBSTR(str);
Marshal.FreeBSTR((IntPtr)bstr);
他们有特殊的处理,因为他们的真实的起始地址等(BSTR - 2)(他们有一个
的Int32
prepended,其长度)
They have special handling because their "real" start address is like (bstr - 2) (they had an
Int32
prepended with their length)
的一点是,居然有分配器的沙漠沙粒和满天的星星。他们每个人(除了.NET的标准之一,使用
一个新的
)都有相应的释放器。他们去像夫妻。他们不混用他人。
The point is that there are as many allocators as the grain of sand of the desert and the stars of the sky. Every one of them (with the exception of the standard one of .NET, the one used by
new
) has a corresponding deallocator. They go like husband and wife. They don't mix with others.
最后要注意,如果你写混合.NET /本地C或C ++ code,你就必须要揭露一些C / C ++中的方法调用的的
免费
/ 删除
,因为他们的免费
/ 删除
是他们的C / C ++库的一部分,该操作系统没有。
As a final note, if you write mixed .NET/native C or C++ code, you'll have to expose some C/C++ methods that call their
free
/delete
, because their free
/delete
are part of their C/C++ libraries, not of the OS.
这篇关于删除C#不安全的指针的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!