COM中的内存管理

时间:2012-02-16 09:45:19

标签: com

在执行COM服务器期间分配一块内存,然后通过输出参数将该内存块传递给客户端是很常见的。然后,客户有义务使用CoTaskMemFree()等方法释放内存。

问题是,这块内存分配在哪里?假设COM服务器和COM客户端在不同的进程中,为了让客户端访问该内存块,应该在客户端的进程地址空间中分配。但这是真的吗?我听说COM有一个“任务记忆分配器”。但我对此知之甚少。

只是一些猜测:

首先,COM服务器根据COM客户端的请求使用CoTaskMemAlloc()分配内存。

然后,COM客户端获取该内存,使用它,并使用CoTaskMemFree()释放它。

因此“任务内存分配器”必须跟踪客户端和服务器进程。从根本上说,它不知道谁(服务器)执行了内存分配操作以及谁(客户端)应该给予该内存。然后,分配的内存将以某种方式注入到客户端的进程地址空间。

有人能说清楚这个话题吗?

3 个答案:

答案 0 :(得分:4)

好吧,“任务内存分配器”是一个COM拥有的分配器,它公开了那些CoTaskMem*函数。现在假设客户端和服务器位于不同的进程中,服务器使用CoTaskMemAlloc()来分配“out”参数。它如何到达客户端?

COM子系统与编组就是这样做的。服务器分配内存并从其COM方法实现返回控制。 COM子系统现在必须将调用结果封送到客户端。它只需拥有该内存的所有权并将其编组给客户端。客户端在其(客户端)堆上分配自己的块,将数据复制到客户端,释放服务器上的块。客户获得该块的所有权,并且必须在以后释放它,否则块被泄露。

因此,客户端和服务器地址空间始终是分开的,不会发生直接数据访问。每个都使用自己的内存分配器,在中间编组,使客户端分配内存并使服务器空闲内存,以便客户端获得合法分配的块的所有权,服务器释放它自己分配的块的所有权。

因此,对于客户端,几乎看起来像服务器分配内存并将其返回给客户端。一个值得注意的例外是允许逻辑地址不同 - 比如服务器在地址0x10001000分配的内存,并将该地址与块一起返回。客户端不能保证将块放在同一个逻辑地址 - 该地址将由客户端分配器决定。

答案 1 :(得分:0)

如果使用CoTaskMemAlloc分配内存块,则最终使用默认的每进程堆(source)分配该内存。

使用 CoTaskMemAlloc 和任何其他分配器之间的区别在于此分配是COM识别的,这意味着COM能够在需要时跨进程边界封送此内存(例如,通过复制内存)

答案 2 :(得分:0)

任务内存分配器分配 where 的内存块的问题是实现细节,我认为这与您无关。但重要的是,此内存分配器为您提供了一个接口和机制,您可以通过该机制分配和释放跨进程边界的内存。

当您分配某个机制(无论是new还是CoTaskMemAlloc)的内存时,您必须使用相应的释放机制。因此,new delete使用CoTaskMemAllocCoTaskMemFree使用{{1}}

OLE分配器将正确地分配和释放内存,即使您在进程X中分配,传递给进程Y然后解除分配。

关键是您使用相同的机制。