0

I created a C++ console app using VC++ 2017. It makes a number of calls over time to retrieve data from a 3rd party COM DLL. I use COM classes like CComSafeArray and CComVariant that manage their own freeing.

Over time I observe that the memory for my App steadily increases in Task Manager after each COM call.

I have used the CRT library (https://learn.microsoft.com/en-us/visualstudio/debugger/finding-memory-leaks-using-the-crt-library?view=vs-2019) to try to detect memory leaks but it indicates I have none.

My question(s) is/are:

  1. Does COM in general do it's own memory management that the CRT library cannot detect but is tied to my process?
  2. If #1 is the case, are there tools available to detect COM memory leaks?
  3. If #1 is the case, is there a way to garbage collect COM memory?

Thanks for your consideration.

Edit 4-19-2019 I have found out that the COM Dll returns VARIANT's and BSTR's for function call results. I am assigning them variously to _variant_t and _bstr_t as applicable to provide automatic cleanup (theoretically). For example.

_variant_t v = GetSomeVariant();
_bstr_t b = GetSomeString();

The DLL does not use CoTaskMemAlloc but it does use SysAllocString to generate the BSTRs.

C Drozdowski
  • 13
  • 1
  • 3
  • Observing memory increase through Task Manager is not really a reliable way to tell memory increasing. When you `delete/delete[]/free/etc` memory then usually it does not go straight back to the OS. It is reserved for later use. – Neijwiert Apr 17 '19 at 09:00
  • Consider looking at the answers in [this question](https://stackoverflow.com/questions/1421491/does-calling-free-or-delete-ever-release-memory-back-to-the-system) – Neijwiert Apr 17 '19 at 09:02
  • Well, if this a modern app then heavy leaks of COM object shouldn't be surprising as MS mostly abandoned weak concept of object lifetime management through reference counting that has been previously used in COM. So instead of tracking COM memory leaks you should probably focus on making your app restart properly after getting killed because of resource exhaust. – user7860670 Apr 17 '19 at 09:06
  • @VTT: I'd downvote that if I could downvote comments. – MSalters Apr 19 '19 at 09:50

2 Answers2

1

COM does not use any automated garbage collection; everything has to be accounted for although there are helper classes available that take care of reference counting.

The convention in COM is that, if the called method allocates some memory then the caller has to free it with CoTaskMemFree. You may want to check your code for the DLL methods that you call and if they return anything in a buffer that was allocated by the DLL then you'll need to free that buffer by calling CoTaskMemFree.

See https://learn.microsoft.com/en-us/windows/desktop/learnwin32/memory-allocation-in-com

More details here: https://learn.microsoft.com/en-us/windows/desktop/com/memory-management-rules

J.R.
  • 1,880
  • 8
  • 16
  • I amended my question (edit noted) to provide some insight about what the COM dll returns and how I assign return values. – C Drozdowski Apr 19 '19 at 09:14
0

_bstr_t b = GetSomeString();

Presumably, that is BSTR GetSomeString();. Which to the compiler meanswchar_t* GetSomeString ; BSTR tells you that it uses COM semantics but the compiler doesn't know that. And those semantics are that you call SysFreeString.

_bstr_t::_bstr_t( wchar_t* str ) copies str. Yes, _bstr_t::~_bstr_t will then call SysFreeString, but it does so on the copy. You needed to call SysFreeString on the BSTR GetSomeString();.

The solution is _bstr_t::_bstr_t( BSTR bstr , bool fCopy ) with fCopy=false. Per MSDN:

This constructor is used by wrapper functions in the type library headers to encapsulate and take ownership of a BSTR that is returned by an interface method.

For VARIANT, see _variant_t::_variant_t(VARIANT& varSrc, bool fCopy);. Same idea.

MSalters
  • 173,980
  • 10
  • 155
  • 350
  • I am willing to accept this answer because it makes sense. However, I have found out that this COM dll leaks serious memory without my pulling any data from it. It opens and closes file system files but seems to not to clean up after itself. So I cannot say for sure that this answer fixes my problem. However, I did adopt the suggestions. – C Drozdowski Apr 20 '19 at 11:56