Marshal.AllocHGlobal(0) - 为什么这不是 return IntPtr.Zero
Marshal.AllocHGlobal(0) - Why does this not return IntPtr.Zero
只是想了解这是否有意义以及其中的意义所在。
Marshal.AllocHGlobal(int cb)
在非托管内存中分配指定数量的字节。
但为什么 Marshal.AllocHGlobal(0)
实际上是 return 一个 IntPtr
而不是 而不是 IntPtr.Zero
?我是否应该在使用完 0 字节后释放分配的 0 字节?
我看不出这个实现背后的逻辑,谁能解释一下?
对于某些用例,对 AllocHGlobal
的两次不同调用永远不会 return 相同 IntPtr
值(缺少任何FreeHGlobal
个调用),即使其中两个调用碰巧指定了一个有点无意义的大小值。
归根结底,您调用此函数可能是出于与期望与 "global" 堆一起工作的非托管代码的互操作目的。并且 GlobalAlloc
长期以来一直被声明接受 0
值,并且该函数实际上总是执行一些分配(如果它成功)。
1。如果分配了 0 个字节,为什么 Marshal.AllocHGlobal
不是 return IntPtr.Zero
?
Marshal.AllocHGlobal
从 WinBase.h
.
内部调用 WinAPI 函数 LocalAlloc
至于为什么Marshal.AllocHGlobal(0)
没有returnIntPtr.Zero
:
LocalAlloc
仅 returns NULL
(C# 等价物:IntPtr.Zero
)以防分配期间发生故障。
这也可以在 source code:
中看到
IntPtr pNewMem = Win32Native.LocalAlloc_NoSafeHandle(LMEM_FIXED, unchecked(numBytes));
if (pNewMem == IntPtr.Zero) {
throw new OutOfMemoryException();
}
return pNewMem;
2。为什么分配 0 个字节 return 一个(有效的)内存地址?
documentation 表示 LocalAlloc
的 return 值:
If the function succeeds, the return value is a handle to the newly allocated memory object.
If the function fails, the return value is NULL
.
现在,LocalAlloc
仅当‡ uBytes
为负数时才会失败;正值或零值都没有问题。
这意味着分配总是会成功‡,如果您尝试分配 0 个字节,您将始终收到一个有效的指针。
‡ 失败还有其他原因,例如内存不足。为简单起见,在此解释中将它们排除在外。
3。我应该释放 Marshal.AllocHGlobal(0)
分配的内存吗?
LocalAlloc
的签名是这样的:
DECLSPEC_ALLOCATOR HLOCAL LocalAlloc(
UINT uFlags,
SIZE_T uBytes
);
if [uBytes
] is zero and the uFlags
parameter specifies LMEM_MOVEABLE
, the function returns a handle to a memory object that is marked as discarded.
出于某种原因,Marshal.AllocHGlobal(0)
不是 通过 LMEM_MOVEABLE
而是 LMEM_FIXED
。
文档缺少有关此特定案例的信息。 运行 测试(见下文)表明实际上正在分配内存,您肯定需要释放内存,如下所示:
IntPtr zeroBytesPtr = Marshal.AllocHGlobal(0);
// Do stuff with the pointer.
Marshal.FreeHGlobal(zeroBytesPtr);
如果 Marshal.AllocHGlobal
传递给 LMEM_MOVEABLE
,则不需要在任何地方释放指针。
至于测试:
while(true) {
void* v = LocalAlloc(LMEM_FIXED, 0);
}
为循环的每次迭代分配内存并且每次returns一个新地址,而
while(true) {
void* v = LocalAlloc(LMEM_MOVEABLE, 0);
}
只分配一次内存并且return每次分配相同的地址。
这表明为什么 Marshal.AllocHGlobal
分配的内存必须被释放(因为它使用 LMEM_FIXED
),因为每次调用都会分配一个新的内存对象。
只是想了解这是否有意义以及其中的意义所在。
Marshal.AllocHGlobal(int cb)
在非托管内存中分配指定数量的字节。
但为什么 Marshal.AllocHGlobal(0)
实际上是 return 一个 IntPtr
而不是 而不是 IntPtr.Zero
?我是否应该在使用完 0 字节后释放分配的 0 字节?
我看不出这个实现背后的逻辑,谁能解释一下?
对于某些用例,对 AllocHGlobal
的两次不同调用永远不会 return 相同 IntPtr
值(缺少任何FreeHGlobal
个调用),即使其中两个调用碰巧指定了一个有点无意义的大小值。
归根结底,您调用此函数可能是出于与期望与 "global" 堆一起工作的非托管代码的互操作目的。并且 GlobalAlloc
长期以来一直被声明接受 0
值,并且该函数实际上总是执行一些分配(如果它成功)。
1。如果分配了 0 个字节,为什么 Marshal.AllocHGlobal
不是 return IntPtr.Zero
?
Marshal.AllocHGlobal
从 WinBase.h
.
LocalAlloc
至于为什么Marshal.AllocHGlobal(0)
没有returnIntPtr.Zero
:
LocalAlloc
仅 returns NULL
(C# 等价物:IntPtr.Zero
)以防分配期间发生故障。
这也可以在 source code:
IntPtr pNewMem = Win32Native.LocalAlloc_NoSafeHandle(LMEM_FIXED, unchecked(numBytes));
if (pNewMem == IntPtr.Zero) {
throw new OutOfMemoryException();
}
return pNewMem;
2。为什么分配 0 个字节 return 一个(有效的)内存地址?
documentation 表示 LocalAlloc
的 return 值:
If the function succeeds, the return value is a handle to the newly allocated memory object.
If the function fails, the return value is
NULL
.
现在,LocalAlloc
仅当‡ uBytes
为负数时才会失败;正值或零值都没有问题。
这意味着分配总是会成功‡,如果您尝试分配 0 个字节,您将始终收到一个有效的指针。
‡ 失败还有其他原因,例如内存不足。为简单起见,在此解释中将它们排除在外。
3。我应该释放 Marshal.AllocHGlobal(0)
分配的内存吗?
LocalAlloc
的签名是这样的:
DECLSPEC_ALLOCATOR HLOCAL LocalAlloc(
UINT uFlags,
SIZE_T uBytes
);
if [
uBytes
] is zero and theuFlags
parameter specifiesLMEM_MOVEABLE
, the function returns a handle to a memory object that is marked as discarded.
出于某种原因,Marshal.AllocHGlobal(0)
不是 通过 LMEM_MOVEABLE
而是 LMEM_FIXED
。
文档缺少有关此特定案例的信息。 运行 测试(见下文)表明实际上正在分配内存,您肯定需要释放内存,如下所示:
IntPtr zeroBytesPtr = Marshal.AllocHGlobal(0);
// Do stuff with the pointer.
Marshal.FreeHGlobal(zeroBytesPtr);
如果 Marshal.AllocHGlobal
传递给 LMEM_MOVEABLE
,则不需要在任何地方释放指针。
至于测试:
while(true) {
void* v = LocalAlloc(LMEM_FIXED, 0);
}
为循环的每次迭代分配内存并且每次returns一个新地址,而
while(true) {
void* v = LocalAlloc(LMEM_MOVEABLE, 0);
}
只分配一次内存并且return每次分配相同的地址。
这表明为什么 Marshal.AllocHGlobal
分配的内存必须被释放(因为它使用 LMEM_FIXED
),因为每次调用都会分配一个新的内存对象。