C# 如果它在本地堆上分配,为什么称为Marshal.AllocHGlobal?
从MSDN文档中: AllocHGlobal是封送处理类中的两种内存分配方法之一。此方法公开Kernel32.dll中的Win32 LocalAlloc函数 考虑到有一个GlobalAlloc API在全局堆而不是本地堆上分配内存,这个方法的名称不是很容易引起误解吗 是否有理由将其命名为C# 如果它在本地堆上分配,为什么称为Marshal.AllocHGlobal?,c#,winapi,memory-management,marshalling,C#,Winapi,Memory Management,Marshalling,从MSDN文档中: AllocHGlobal是封送处理类中的两种内存分配方法之一。此方法公开Kernel32.dll中的Win32 LocalAlloc函数 考虑到有一个GlobalAlloc API在全局堆而不是本地堆上分配内存,这个方法的名称不是很容易引起误解吗 是否有理由将其命名为AllocHGlobal,而不是alloclocal 更新:Simon在评论中指出,Windows中不再存在全局堆,而GlobalAlloc和LocalAllocAPI仅用于遗留用途。如今,GlobalAlloc
AllocHGlobal
,而不是alloclocal
更新:Simon在评论中指出,Windows中不再存在全局堆,而GlobalAlloc
和LocalAlloc
API仅用于遗留用途。如今,GlobalAlloc
API只不过是LocalAlloc
的包装器
这解释了为什么API根本不调用
GlobalAlloc
,但它没有解释为什么API在不(不能)使用全局堆的情况下被命名为AllocHGlobal
,甚至也没有调用GlobalAlloc
。由于遗留的原因,命名不可能被使用,因为它是在.NET2.0之前才引入的,这是在16位支持被放弃之后。因此,问题仍然存在:为什么Marshal.AllocHGlobal
的名称如此误导?这可以追溯到Windows版本3的早期。当时有一个“默认堆”的概念,即从中分配的GlobalAlloc()api函数。从该堆分配的内存可以在所有进程之间共享
这在32位版本的Windows中发生了变化,进程不能再通过堆共享内存。这使得术语“全局堆”和“局部堆”毫无意义。还有一个默认堆的概念,即“进程堆”。GlobalAlloc()现在从该堆进行分配。但它不能跨流程边界共享。GlobalAlloc和Marshal.AllocHGlobal的实际实现使用LocalAlloc()api函数。另一个Windows3的延期,有点更适合命名为这些天发生的事情。它反过来在32位Windows上使用HeapAlloc()和GetProcessHeap()
同意使用堆是一个重要的互操作问题。在编写得很糟糕的C代码中,这经常出错。任何这样的代码返回指向需要调用方释放的已分配内存的指针,通常由于内存泄漏或访问冲突而失败。这样的C代码使用malloc()函数从自己的堆中进行分配。它是由C运行时库创建的私有堆。您不可能释放这样的内存,您不知道使用了什么堆,也无法获得CRT堆的句柄
这只有在C代码使用众所周知的堆时才能有好的结果。就像进程堆一样。或CoTaskMemAlloc(),由COM代码使用。封送员类中的另一个。请注意,pinvoke marshaller总是在必要时使用CoTaskMemFree()释放内存。如果未使用CoTaskMemAlloc()分配内存,则Vista和更高版本上会出现这种情况。假设您使用拖放或剪贴板在应用程序之间进行数据传输。要填充结构,需要一个
HGLOBAL
。因此,您可以调用AllocHGlobal
。因此得名
此函数的主要用途是与需要HGLOBAL
的API进行互操作。如果它被称为其他名称,那将令人困惑,因为当你想要一个HGLOBAL
时,你必须找到一些文档,告诉你allocanythingthese
产生了一个可以用作HGLOBAL
的值,我想你应该阅读
其中的一小部分:
全局和本地内存功能乍一看
Windows中存在本地和全局内存管理功能
与Windows 3.1版向后兼容。这可能是真的,
但是这些函数的管理效率与新的堆函数一样高
下面讨论。事实上,从16位Windows移植应用程序
不一定包括从全局和本地内存迁移
函数来堆内存函数。全局和局部功能
提供相同的基本功能(还有一些),速度也一样快
一起工作。如果有什么不同的话,他们可能更方便工作
使用,因为您不必跟踪堆句柄
尽管如此,这些功能的实现与
它适用于16位Windows。16位Windows有一个全局堆,每个
应用程序有一个本地堆。这两个堆管理器实现了
全局和局部功能。通过GlobalAlloc分配内存
从全局堆中检索内存块,而LocalAlloc
从本地堆分配的内存。Windows现在只有一个堆
对于这两种类型的函数,都使用上面描述的默认堆
现在,您可能想知道
本地和全局功能本身。答案是否定的,他们
现在都一样了。事实上,它们是可以互换的。内存分配
通过调用LocalAlloc,可以使用GlobalReAlloc和
然后被LocalLock锁定。下表列出了全局和全局变量
本地功能现在可用
有两组功能可以精确执行,这似乎是多余的
同样,但这就是向后兼容性的原因。
在16位Windows中使用全局函数还是本地函数
以前的应用程序并不重要,现在它们同样有效
等等
而且记忆在过去是非常昂贵的。另外,请参阅PostScript语言参考手册,该手册可能会让您对本地/全局内存的使用有一个很好的了解。Fyi,LocalAlloc和GlobalAlloc都有“Windows内存管理不提供单独的本地堆和全局堆。因此,LocalAlloc和GlobalAlloc函数