gpt4 book ai didi

c# - Marshal.AllocHGlobal(0) - 为什么这不返回 IntPtr.Zero

转载 作者:太空狗 更新时间:2023-10-30 00:59:53 36 4
gpt4 key购买 nike

只是想了解这是否有意义,以及它的意义在哪里。

Marshal.AllocHGlobal(int cb) 在非托管内存中分配指定数量的字节。

但为什么 Marshal.AllocHGlobal(0) 实际上返回一个 IntPtr 而不是 IntPtr.Zero ?我是否应该在使用完 0 字节后释放分配的 0 字节?

我看不出这个实现背后的逻辑,谁能解释一下?

最佳答案

1。如果分配了 0 个字节,为什么 Marshal.AllocHGlobal 不返回 IntPtr.Zero

Marshal.AllocHGlobal 内部调用 WinAPI 函数 LocalAlloc来自 WinBase.h

至于为什么Marshal.AllocHGlobal(0)不返回IntPtr.Zero:LocalAlloc 仅在分配期间发生故障时返回 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 个字节会返回一个(有效的)内存地址?

documentation说到LocalAlloc的返回值:

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
);

documentation指出

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);
}

为循环的每次迭代分配内存并每次返回一个新地址,而

while(true) {
void* v = LocalAlloc(LMEM_MOVEABLE, 0);
}

只分配一次内存并返回每次都相同的地址

这表明为什么必须释放由 Marshal.AllocHGlobal 分配的内存(因为它使用 LMEM_FIXED),因为每次调用都会分配一个新的内存对象。

关于c# - Marshal.AllocHGlobal(0) - 为什么这不返回 IntPtr.Zero,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52073336/

36 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com