2

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:

Usage of CoTaskMemAlloc?

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().

Community
  • 1
  • 1
Robert Oschler
  • 14,153
  • 18
  • 94
  • 227
  • 1
    I don't see why `CoTaskMemAlloc` would help with memory that crosses process boundaries. My understanding is that you use `CoTaskMemAlloc` whenever you pass ownership of memory to another COM object. – David Heffernan Oct 26 '11 at 21:53

2 Answers2

3

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.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • 1
    To add to this, in OP's case one should be using `CoTaskMemAlloc` when documentation instructs to do so. E.g. "a buffer needs to be allocated with `CoTaskMemAlloc` and it is a caller's responsibility to free it". In DirectShow it is typically around `AM_MEDIA_TYPE` structure so that various software components could be passing blocks of data from one to another. – Roman R. Oct 27 '11 at 07:15
  • @roman documentation rarely calls out COM allocator explicitly. You are meant to know about that as a pre-requisite. Docs usually say, "the caller must free the memory returned" and so on. That is code for, "use COM allocator". – David Heffernan Oct 27 '11 at 07:20
  • A good part of DirectShow doc is written 15 years ago and it sais it clearly "The caller must free the media type's format block. You can use the Microsoft® Win32® CoTaskMemFree function, or the FreeMediaType helper function." E.g. http://msdn.microsoft.com/en-us/library/windows/desktop/dd390422%28v=VS.85%29.aspx – Roman R. Oct 27 '11 at 07:24
  • @roman I must have been looking at a different part of the docs – David Heffernan Oct 27 '11 at 07:28
1

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.

MartyTPS
  • 530
  • 2
  • 5
  • Thanks @MartyTPS. Should I always use CoTaskMemFree() for such allocations? I have seen a few samples where memory allocated with CoTaskMemAlloc() during GetMediaType() calls is never freed, like when memory is allocated for the VIDEOINFOHEADER structure and assigned to the MediaType object parameter's pbFormat pointer in a video Filter, before the call exits. Is that a leak or is that to avoid causing a previous caller to the Filter's GetMediaType() method a severe error if they still hold a reference to that memory and you free it? – Robert Oschler Oct 27 '11 at 00:19
  • 2
    You actually marked the wrong answer as correct. DriectShow filters do `NOT` use CoTaskMemAlloc-allcoated buffers to pass payload data between them. They use this memory allocator to allocate media type data, so that a value allocated by one filter could be passed to another along with responsibility to free memory when no longer needed. The other answer (David's) is definitely a better fit. – Roman R. Oct 27 '11 at 07:10
  • CoTaskMemAlloc is intended to be freed by someone else. – MartyTPS Oct 27 '11 at 14:12
  • I would say that anytime you are using COM and not just allocating somethign for your personal use, you will use CoTaskMemAlloc. – MartyTPS Oct 27 '11 at 14:21