何时以及为何在 DirectShow 过滤器中使用 CoTaskMemAlloc()?
我正在使用 DSPACK DirectShow 组件库在 Delphi 6 Pro 中构建 DirectShow Filter。在他们的推送源过滤器示例中,对于某些项目,他们使用 CoTaskMemAlloc(),特别是为 Windows API 调用中使用的项目分配内存,例如视频位图信息标头 (PVIDEOINFOHEADER) 和 O/S 文件操作中使用的缓冲区,例如 ReadFile 等其他项目使用通常的 (Object).Create() 调用或直接创建动态数组来分配。
当您必须在 DirectShow 过滤器中使用 CoTaskMemAlloc() 时,有哪些规则/准则?
@Vinay 的回复给出了简洁的答案,即它应该与任何跨越进程边界的内存一起使用:
但我想知道在 DirectShow 过滤器中是否可能犯任何常见的内存分配错误,特别是在通过渲染或提供数据时输入/输出引脚,由于我未能使用 CoTaskMemAlloc()。
I am building a DirectShow Filter in Delphi 6 Pro using the DSPACK DirectShow component library. In their Push Source Filter example, for some items they use CoTaskMemAlloc(), especially with allocating memory for items used in Windows API calls such as video bitmap info headers (PVIDEOINFOHEADER) and buffers used in O/S file operations such as ReadFile, etc. Other items are allocated using the usual (Object).Create() call or by creating dynamic arrays directly.
What are the rules/guidelines for when you must use CoTaskMemAlloc() inside a DirectShow filter?
This SO reply by @Vinay gives the succinct answer that it should be used with any memory that will crosses process boundaries:
But I would like to know if there are any common memory allocation mistakes I am likely to make in my DirectShow filter, especially when rendering or providing data via input/output pins, due to my failure to use CoTaskMemAlloc().
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
CoTaskMemAlloc 是 COM 内存分配器的一部分。它与 CoTaskMemRealloc 和 CoTaskMemFree 一起使用。
COM 内存分配器旨在允许 COM 客户端分配随后由 COM 服务器释放的内存,反之亦然。仅当内存所有权跨 COM 客户端/服务器边界转移时才需要使用它。
这解决了一个非常常见的互操作问题。不同的编程系统对堆有不同的实现。因此,在一个堆上分配的内存只能在同一堆上释放。比如说,如果您有一个返回字符串的 COM 方法,那么您就会遇到问题。如果服务器和客户端使用不同的堆,您现在需要要求服务器在使用完字符串后释放该字符串。 COM 分配器通过成为所有参与者都可以使用的单个共享堆来解决这个问题。
话虽如此,得知 BSTR(即 Delphi 中所谓的 WideString)是用 COM 分配器分配的,也就不足为奇了。
我不熟悉 DirectShow 接口,但 COM 的原理是通用的。当您在服务器中实现 GetMediaType 时,您必须分配返回的结构。由于客户端必须释放该结构(如文档中所指定),因此显然您必须使用 COM 分配器,因为这就是您的客户端将使用的。
您还提到了 ReadFile。这里根本没有必要使用 COM 分配器,因为调用者负责分配和释放缓冲区。
底线是 COM 是一个接口契约。如果指针跨越接口边界并且所有权从客户端转移到服务器,反之亦然,则必须使用 COM 分配器。
CoTaskMemAlloc is part of the COM memory allocator. It is used with CoTaskMemRealloc and CoTaskMemFree.
The COM memory allocator is designed to allow a COM client to allocate memory that is later freed by the COM server or vice versa. You only need to use it when ownership of the memory is transferred across the COM client/server boundary.
This solves a very common interop problem. Different programming systems have different implementations for heaps. Consequently memory allocated on one heap can only be deallocated on the same heap. If you have a COM method that returns a string, say, you have a problem. If the server and client use different heaps you now need to ask the server to deallocate the string when you are done with it. The COM allocator solves this by virtue of being a single, shared heap that all participants can use.
Having said this it should come as no surprise to learn that a BSTR, i.e. what is called WideString in Delphi, is allocated with the COM allocator.
I'm not familiar with the DirectShow interfaces but the principles of COM are universal. When you implement GetMediaType in your server you must allocate the struct that is returned. Since the client has to free that struct, as specified in the documentation, clearly you must use the COM allocator since that is what your clients will use.
You also mentioned ReadFile. No point at all using COM allocator here since the caller is responsible for both allocating and freeing the buffer.
The bottom line is that COM is an interface contract. If a pointer crosses the interface boundary and has ownership transferred from client to server, or vice versa, then the COM allocator must be used.
您必须使用 CoTaskMemAlloc 来分配 COM 中将传递给外部世界的任何内存。 Directshow 过滤器使用 COM 并将缓冲区从一个过滤器传递到另一个过滤器,以避免复制数据。
You MUST use CoTaskMemAlloc for any allocation of memory in COM that will be passed to the outside world. Directshow filtrers use COM and pass the buffers from filter to filter to avoid copying the data.