组件对象模型 (COM):IMalloc::Alloc 在哪里分配内存?
Component Object Model (COM): Where does IMalloc::Alloc allocate memory?
正在为一些遗留项目读入 COM。到目前为止,我的理解是 COM 只是一个二进制规范,所有实现组件(客户端和服务器)都必须遵守这个规范。只要我们使用仅接收和返回简单值类型的方法处理 COM 接口,一切对我来说都非常有意义。
但是,也可以将 指针 发送到整个 objects/variants(包含例如 SAFEARRAY
)from/to COM 对象,我想知道这些参数对象的内存分配在哪里。我读到它是 windows 拥有的内存,我们不应该篡改它,除非通过 COM 方法。
然后我偶然发现了 IMalloc
COM 接口及其 Alloc
方法,它似乎以 COM 感知的方式分配了一堆内存,完美地解决了这个问题。
为了不干扰由例如维护的堆结构C++(假设我们正在用 C++ 编写 COM 服务器),IMalloc
究竟在哪里分配内存?
我对这个问题的回答是:我不知道也不关心。
你做要做的就是遵守规则。 COM(和 COM 对象)可以以它们选择的任何方式自由分配内存,您可能对它们在哪里或如何做的任何假设都是危险和不必要的。可能,最后,它最终是通过 HeapAlloc()
分配的,但它不一定是,即使它是你肯定不知道 哪个 堆。
在调用 COM 对象时由客户端分配内存(通过 CoTaskMemAlloc()
,比方说)相对较少。更常见的是 COM 对象分配它需要的任何内存以打包调用结果,然后 return 你一个指针 - 通常以另一个 COM 对象的形式 - 你可以将其用于任何你接下来需要做的。相关方法的 API 文档将告诉您在使用完该指针后该做什么,这就是您需要知道的全部内容。这种确切的机制因 API 而异,例如:
对于 COM 对象调用 Release();
对象(这通常是隐含的,而不是在文档中明确调用)。
对于 'raw' 指针,文档可能会告诉您调用或 CoTaskMemFree()
或者 IMalloc::Free()
.
对于 SAFEARRAY 调用 SafeArrayUnaccessData()
/ SafeArrayUnlock()
/ SafeArrayDestroy()
.
有时候你需要调用一些有点离谱的东西,比如SysFreeString()
.
无论如何 - 总是 - 对于任何特定的 API,请阅读文档,你应该没问题。
Windows 用于为 COM 分配创建专用堆,CoTaskMemAlloc() 直接从中分配它。然而,它在 Win8 中被删除了,它现在从默认进程堆 GetProcessHeap() returns 中分配。 VS2012 的 Microsoft CRT 也发生了变化,以前有自己的堆,但现在也使用默认进程堆。
进行这些更改的确切原因对我来说是模糊的,我从来没有看到一个很好的解释。但不太可能与 WinRT(又名 UWP,又名 Windows Store,又名 Modern UI)有关。引擎盖下主要由 COM 驱动,但语言投影提供了非常紧密的语言运行时集成。或者只是为了绕过这些不同堆过去经常造成的麻烦。特别是 CRT 堆是一个 DLL 地狱噩梦,程序在新的 VS 版本上重建但仍然使用旧的 DLL 时会惨败。
正在为一些遗留项目读入 COM。到目前为止,我的理解是 COM 只是一个二进制规范,所有实现组件(客户端和服务器)都必须遵守这个规范。只要我们使用仅接收和返回简单值类型的方法处理 COM 接口,一切对我来说都非常有意义。
但是,也可以将 指针 发送到整个 objects/variants(包含例如 SAFEARRAY
)from/to COM 对象,我想知道这些参数对象的内存分配在哪里。我读到它是 windows 拥有的内存,我们不应该篡改它,除非通过 COM 方法。
然后我偶然发现了 IMalloc
COM 接口及其 Alloc
方法,它似乎以 COM 感知的方式分配了一堆内存,完美地解决了这个问题。
为了不干扰由例如维护的堆结构C++(假设我们正在用 C++ 编写 COM 服务器),IMalloc
究竟在哪里分配内存?
我对这个问题的回答是:我不知道也不关心。
你做要做的就是遵守规则。 COM(和 COM 对象)可以以它们选择的任何方式自由分配内存,您可能对它们在哪里或如何做的任何假设都是危险和不必要的。可能,最后,它最终是通过 HeapAlloc()
分配的,但它不一定是,即使它是你肯定不知道 哪个 堆。
在调用 COM 对象时由客户端分配内存(通过 CoTaskMemAlloc()
,比方说)相对较少。更常见的是 COM 对象分配它需要的任何内存以打包调用结果,然后 return 你一个指针 - 通常以另一个 COM 对象的形式 - 你可以将其用于任何你接下来需要做的。相关方法的 API 文档将告诉您在使用完该指针后该做什么,这就是您需要知道的全部内容。这种确切的机制因 API 而异,例如:
对于 COM 对象调用
Release();
对象(这通常是隐含的,而不是在文档中明确调用)。对于 'raw' 指针,文档可能会告诉您调用或
CoTaskMemFree()
或者IMalloc::Free()
.对于 SAFEARRAY 调用
SafeArrayUnaccessData()
/SafeArrayUnlock()
/SafeArrayDestroy()
.有时候你需要调用一些有点离谱的东西,比如
SysFreeString()
.
无论如何 - 总是 - 对于任何特定的 API,请阅读文档,你应该没问题。
Windows 用于为 COM 分配创建专用堆,CoTaskMemAlloc() 直接从中分配它。然而,它在 Win8 中被删除了,它现在从默认进程堆 GetProcessHeap() returns 中分配。 VS2012 的 Microsoft CRT 也发生了变化,以前有自己的堆,但现在也使用默认进程堆。
进行这些更改的确切原因对我来说是模糊的,我从来没有看到一个很好的解释。但不太可能与 WinRT(又名 UWP,又名 Windows Store,又名 Modern UI)有关。引擎盖下主要由 COM 驱动,但语言投影提供了非常紧密的语言运行时集成。或者只是为了绕过这些不同堆过去经常造成的麻烦。特别是 CRT 堆是一个 DLL 地狱噩梦,程序在新的 VS 版本上重建但仍然使用旧的 DLL 时会惨败。