- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
只是想了解这是否有意义,以及它的意义在哪里。
Marshal.AllocHGlobal(int cb)
在非托管内存中分配指定数量的字节。
但为什么 Marshal.AllocHGlobal(0)
实际上返回一个 IntPtr
而不是 IntPtr.Zero
?我是否应该在使用完 0 字节后释放分配的 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;
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 个字节,您将始终收到一个有效的指针。
‡ 失败还有其他原因,例如内存不足。为简单起见,在此解释中将它们排除在外。
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);
}
为循环的每次迭代分配内存并每次返回一个新地址,而
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/
我正在尝试使用 BitmapData 类?并且在将 IntPtr 值分配给 BitmapData.Scan0 属性时遇到一些问题。这是我的代码: var data = bmp.LockBits(new
我正在尝试使用 BitmapData 类?并且在将 IntPtr 值分配给 BitmapData.Scan0 属性时遇到一些问题。这是我的代码: var data = bmp.LockBits(new
我有两个 IntPtr 值指向一些 length 字节的数据区域。 length 可能有 200k 到 400k 的数量级。 int length = /* ..*/ IntPtr ptrSrc =
我在网上到处都看过,似乎找不到能够解决该问题的特定答案。从字面上看,这是我得到的唯一错误,只有在解决此问题后才能构建可执行文件。 int num3 = new VAMemory(Data.proces
我不知道 Copy(IntPtr[], Int32, IntPtr, Int32) 方法是如何工作的。我虽然它可以将多个 IntPtr 中包含的数据复制到一个 IntPtr 中(如 MSDN 所述),
我有一个类的以下代码。这是一个类的初始化。 第三方动态链接库 [DllImport("gdi32.dll")] public static extern IntPtr CreateCompatib
我刚刚了解到 IntPtr.Zero 无法与 default(IntPtr) 相提并论。谁能告诉我为什么? IntPtr.Zero == new IntPtr(0) -> "could not eva
这两种说法有什么区别吗: IntPtr myPtr = new IntPtr(0); IntPtr myPtr2 = IntPtr.Zero; 我见过许多使用 PInvoke 的示例,如果 myPtr
这个问题已经有答案了: What makes more sense - char* string or char *string? [duplicate] (13 个回答) 已关闭 9 年前。 本能地
我知道 Marshal.SizeOf() 和 sizeof() 有多么根本的不同。但是在 IntPtr 的情况下,无论 CPU 架构如何,它们都不会总是返回完全相同的东西吗? 最佳答案 一方面,有原始
我需要实现一个与找到的解决方案非常相似的解决方案 here ,写于 2009 年,用于检索文件的唯一标识符。具体来说,我正在查看答案的 ApproachB()函数和以下行(重写了一点以反射(refle
是否可以通过 Skype 用户窗口获取处理程序并使用 SendMessage(whdl,BM_CLICK,intptr.zero,intrptr.zero,intptr.zero) 单击发送文件或调用
经过一些研究我翻译了 pHandle = IntPtr.Zero; 到德尔福 var pHandle: Pointer; 当我在 Delphi 中中断调试时,我得到 $314328,当我在 C s
运营商的description on MSDN有一句话: An exception is only thrown if the value of value requires more bits th
这个函数在一个循环中。当我运行程序时,带有 IntPtr 的行给我内存问题,我已经删除 [],但它仍然没有解决内存问题,有人可以帮忙吗?谢谢 void showImage(IplImage *img,
直到最近,我还认为在 P/Invoke 中编码 IntPtr 只会涉及“blitting”操作;即简单地从例如复制指针C++ 到 C#。 然而,我最近与某人交谈时提到,事情远不止于此。他特别提到 In
我目前正在编写一些代码,这些代码反射(reflect)了从对 native dll 的调用中编码返回的结构。一些结构包含指向以 null 结尾的指针数组的 IntPtr* 字段。这些字段需要特殊处理。
我正在尝试在 Ubuntu 14.04 上使用 Mono 执行函数 P/Invoke: [DllImport(@"libRT", CharSet = CharSet.Ansi, CallingConv
我有一个类定义如下: [StructLayout(LayoutKind.Sequential)] public class OUR_MEM_STR {
我遇到了一段C#源码如下 int* ptr = ...; int w = ...; int* ptr3 = ptr + (IntPtr)w; CS0019: Operator '+' cannot
我是一名优秀的程序员,十分优秀!