cog*_*el0 4 .net c# marshalling
只是想了解这是否有意义以及其中的意义在哪里。
Marshal.AllocHGlobal(int cb)在非托管内存中分配指定数量的字节。
但为什么Marshal.AllocHGlobal(0)实际上会返回一个IntPtrnot呢 IntPtr.Zero?当我使用完 0 字节后,我是否应该释放分配的 0 字节?
我看不到这个实现背后的逻辑,有人可以解释一下吗?
Marshal.AllocHGlobal不返回?IntPtr.ZeroMarshal.AllocHGlobalLocalAlloc在内部调用WinAPI 函数WinBase.h。
至于为什么Marshal.AllocHGlobal(0)不返回IntPtr.Zero:\nLocalAlloc仅在分配期间失败的情况下返回NULL(C# 等效: )。\n这也可以在源代码IntPtr.Zero中看到:
IntPtr pNewMem = Win32Native.LocalAlloc_NoSafeHandle(LMEM_FIXED, unchecked(numBytes));\n\nif (pNewMem == IntPtr.Zero) {\n throw new OutOfMemoryException();\n}\nreturn pNewMem;\nRun Code Online (Sandbox Code Playgroud)\n文档中提到了以下的返回值LocalAlloc:
\n\n如果函数成功,返回值是新分配的内存对象的句柄。
\n如果函数失败,则返回值为
\nNULL。
现在,LocalAlloc 仅当\xe2\x80\xa1uBytes为负数时才会失败;正值或零值都没有问题。
这意味着分配始终会成功\xe2\x80\xa1,并且如果您尝试分配 0 字节,您将始终收到有效的指针。
\n\xe2\x80\xa1 失败还有其他原因,例如内存不足。为简单起见,本解释中省略了它们。
\nMarshal.AllocHGlobal(0)吗?的签名LocalAlloc是这样的:
DECLSPEC_ALLOCATOR HLOCAL LocalAlloc(\n UINT uFlags,\n SIZE_T uBytes\n);\nRun Code Online (Sandbox Code Playgroud)\n该文档指出
\n\n\n如果 [
\nuBytes] 为零且uFlags参数指定LMEM_MOVEABLE,则该函数返回标记为已丢弃的内存对象的句柄。
由于某种原因,Marshal.AllocHGlobal(0)没有通过LMEM_MOVEABLE而是相反LMEM_FIXED。
该文档缺乏有关此特定案例的信息。运行测试(见下文)表明内存实际上正在被分配,并且您肯定需要释放内存,如下所示:
\nIntPtr zeroBytesPtr = Marshal.AllocHGlobal(0);\n\n// Do stuff with the pointer.\n\nMarshal.FreeHGlobal(zeroBytesPtr);\nRun Code Online (Sandbox Code Playgroud)\n如果Marshal.AllocHGlobal改为传递LMEM_MOVEABLE,则无需在任何地方释放指针。
至于测试:
\nwhile(true) {\n void* v = LocalAlloc(LMEM_FIXED, 0);\n}\nRun Code Online (Sandbox Code Playgroud)\n为循环的每次迭代分配内存并每次返回一个新地址,而
\nwhile(true) {\n void* v = LocalAlloc(LMEM_MOVEABLE, 0);\n}\nRun Code Online (Sandbox Code Playgroud)\n仅分配内存一次并每次返回相同的地址。
\n这表明为什么分配的内存Marshal.AllocHGlobal必须被释放(因为它使用LMEM_FIXED),因为每次调用都会分配一个新的内存对象。