5

来自 MSDN 文档Marshal.AllocHGlobal

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

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

命名它是有原因的AllocHGlobal,而不是AllocHLocal

更新: Simon 在评论中指出,Windows 中不再有全局堆之类的东西,GlobalAlloc并且LocalAllocAPI 仅用于遗留目的。如今,GlobalAllocAPI 只不过是LocalAlloc.

这解释了为什么 API 根本不调用GlobalAlloc,但没有解释为什么 API 在AllocHGlobal不(不能)使用全局堆时命名,甚至不调用GlobalAlloc. 命名不可能是出于遗留原因,因为它直到 .NET 2.0 才引入,在 16 位支持被删除之后。所以,问题仍然存在:为什么会Marshal.AllocHGlobal如此误导性地命名?

4

3 回答 3

3

假设您正在使用拖放或剪贴板在应用程序之间进行数据传输。要填充STGMEDIUM结构,您需要一个HGLOBAL. 所以你打电话AllocHGlobal。由此得名。

此函数的主要用途是与需要HGLOBAL. 如果它被称为其他任何东西会令人困惑,因为当您想要 an 时,HGLOBAL您必须找到一些文档来告诉您AllocAnythingElse产生的值可以用作HGLOBAL.

于 2012-10-09T10:02:32.490 回答
2

这可以追溯到 Windows 版本 3 的旧时代。当时有一个“默认堆”的概念,即从中分配的 GlobalAlloc() api 函数。从该堆分配的内存可以在所有进程之间共享。

这在 32 位版本的 Windows 中发生了变化,进程不能再通过堆共享内存。这使得术语“全局堆”和“本地堆”变得毫无意义。还有一个默认堆的概念,即“进程堆”。GlobalAlloc() 现在从该堆分配。但它不能跨进程边界共享。GlobalAlloc 和 Marshal.AllocHGlobal 的实际实现使用 LocalAlloc() api 函数。另一个 Windows 3 保留,更恰当地命名为这些天发生的事情。它又在 32 位 Windows 上使用 HeapAlloc() 和 GetProcessHeap()。

同意使用堆是一个重要的互操作问题。这在您调用的编写不佳的 C 代码中经常出错。任何返回指向需要由调用者释放的已分配内存的指针的此类代码通常由于内存泄漏或访问冲突而失败。此类 C 代码使用 malloc() 函数从其自己的堆中分配。这是由 C 运行时库创建的私有堆。你没有希望释放这样的内存,你不知道使用了什么堆,也没有办法获得 CRT 堆的句柄。

只有当 C 代码使用众所周知的堆时,这才能有好的结果。就像进程堆一样。或 CoTaskMemAlloc(),由 COM 代码使用。另一个是元帅级的。请注意,pinvoke 编组器总是在必要时使用 CoTaskMemFree() 释放内存。如果没有使用 CoTaskMemAlloc() 分配内存,那么这在 Vista 及更高版本上是一个 kaboom,这是 XP 上的无声泄漏。

于 2012-10-08T11:21:26.120 回答
1

我认为您应该阅读https://msdn.microsoft.com/en-us/library/ms810603.aspx

一小部分:

全局和局部内存功能 乍一看,Windows 中存在局部和全局内存管理功能纯粹是为了向后兼容 Windows 3.1 版。这可能是真的,但是这些函数的管理与下面讨论的新堆函数一样有效。事实上,从 16 位 Windows 移植应用程序并不一定包括从全局和本地内存功能迁移到堆内存功能。全局和本地功能提供相同的基本功能(然后是一些功能),并且使用起来同样快速。如果有的话,使用它们可能更方便,因为您不必跟踪堆句柄。

尽管如此,这些功能的实现与 16 位 Windows 不同。16 位 Windows 有一个全局堆,每个应用程序都有一个本地堆。这两个堆管理器实现了全局和局部功能。通过 GlobalAlloc 分配内存意味着从全局堆中检索一块内存,而 LocalAlloc 从本地堆中分配内存。Windows 现在为这两种类型的函数提供了一个单一的堆——上面描述的默认堆。

现在您可能想知道本地函数和全局函数本身之间是否有任何区别。好吧,答案是否定的,它们现在是一样的。事实上,它们是可以互换的。通过调用 LocalAlloc 分配的内存可以使用 GlobalReAlloc 重新分配,然后由 LocalLock 锁定。下表列出了现在可用的全局和局部函数。

拥有两组执行完全相同的函数似乎是多余的,但这就是向后兼容性的用武之地。以前在 16 位 Windows 应用程序中使用全局函数还是局部函数现在都无关紧要了——它们同样有效.

ETC...

在过去,内存也非常昂贵。还可以查看 PostScript 语言参考手册,它可能会让您对本地/全局内存的使用有一个很好的了解。

于 2017-04-25T12:01:07.793 回答