C# 如果它在本地堆上分配,为什么称为Marshal.AllocHGlobal?

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

从MSDN文档中:

AllocHGlobal是封送处理类中的两种内存分配方法之一。此方法公开Kernel32.dll中的Win32 LocalAlloc函数

考虑到有一个GlobalAlloc API在全局堆而不是本地堆上分配内存,这个方法的名称不是很容易引起误解吗

是否有理由将其命名为
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函数