Reputation: 13
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:
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.
Upvotes: 0
Views: 391
Reputation: 179819
_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.
Upvotes: 0
Reputation: 1978
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
Upvotes: 1