CoTaskMemAlloc的用法是什么?

16

何时适合使用CoTaskMemAlloc?能否举个例子?


我在下面发布了一些关于何时需要使用CoTaskMemAlloc的信息,但是为了回答你的问题,提供一些上下文可能会有所帮助... - reuben
稍微修改了问题和标题。 - mmcdole
5个回答

21

Foo() 返回的资源何时被释放?或者需要手动释放吗? - chtenb
@ChieltenBrinke CLR将遵循与所有其他托管资源相同的GC规则来管理该资源。 - zz3599
@zz3599 这是什么意思?CLR 需要知道对该内存的所有引用。但在调用 CoTaskMemAlloc 时,我们仍处于非托管代码中,因此就 CLR 而言,没有对该内存的引用。但这意味着在分配完内存后,该内存可能会被回收,这显然不是这个例子的情况。问题是:它是如何工作的? - chtenb
假设您对Foo()返回值保持了托管引用,那么内存将不会被回收。您不再需要负责释放它。 - zz3599

13

哇,我得想一会儿才能理解这个 -- 我曾经用 ATL 做过一些小型 COM 编程,很少需要使用它。

不过,我想到了一个情况:Windows Shell 扩展。如果你正在处理一组文件系统对象,你可能需要处理 PIDLs (指向 ID 列表的指针)。这些是奇怪的小型文件系统对象抽象,需要使用一个支持 COM 的分配器(如 CoTaskMemAlloc)显式地进行分配和释放。还有另一种选择,即从 SHGetMalloc (已弃用) 或 CoGetMalloc 获取的 IMalloc 接口指针 -- 它只是一个抽象层,可以使用任何适当的内存分配器,使您的代码不会绑定到特定的内存分配器。

使用 CoTaskMemAllocIMalloc 而不是 malloc() 的原因是,内存分配/释放需要是“COM-aware”,以便在运行时一致地执行它们的分配和释放,即使分配和释放是由完全不相关的代码 (例如 Windows 为您的 C++ 代码分配内存,然后释放,或者您的 C++ 代码分配内存,将其传输到其他人的 VB 代码,然后释放)。 malloc()new 都不能与系统的运行时堆互操作,因此您不能使用它们来分配内存以传输到其他 COM 对象,也不能接收其他 COM 对象的内存并进行释放。


8
MSDN文章比较了Win32中几种不同的分配器,包括CoTaskMemAlloc。它主要用于COM编程,特别是当COM服务器的实现需要分配内存以返回给客户端时。如果您不编写COM服务器,则可能不需要使用它。
(但是,如果您调用使用CoTaskMemAlloc分配内存并将其返回给您的代码,则需要使用CoTaskMemFree释放返回的分配。)

谢谢Reuben, 我的需求是从comserver进程中分配内存->在comclient侧对其进行realloc,这又是一个不同的进程,然后从comserver侧释放它... 我希望我可以使用cotaskmemxxx函数来实现相同的功能- - atVelu

3

以下调用最终都会得到相同的分配,因此很少会出错:

CoTaskMemAlloc/SHAlloc -> IMalloc.Alloc -> GlobalAlloc(GMEM_FIXED)

只有当您使用非Windows(编译器库)调用,如 malloc() 时,才会出现问题。
正式来说,应该使用 CoTaskMemAlloc 进行 COM 调用(例如分配 FORMATETC.ptd 字段)。
因为 STGMEDIUM 使用剪贴板结构和方法,而 STGMEDIUM 是 COM 类型,因此需要使用 CoTaskMemAlloc,但剪贴板 API 规定需要使用 GlobalAlloc()。这种情况将一直持续到剪贴板 API 和 COM STGMEDIUM 之间的冲突得到解决。

这个逻辑看起来已经是错误的了 - 只要 GlobalAllocCoTaskMemAlloc 使用相同的堆,即 GetProcessHeap 就足够了。这些包装函数可以在不破坏 STGMEDIUM 的情况下添加不同的功能。 - MSalters

2
CoTaskMemAlloc与malloc相同,只是前者用于分配跨进程边界使用的内存。
例如,如果我们有两个进程process1和process2,假设process1是一个COM服务器,而process2是使用process1公开的接口的COM客户端。 如果process1必须发送一些数据,则可以使用CoTaskMemAlloc来分配内存并复制数据。 该内存位置可由process2访问。
COM库自动执行封送和解封送。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接