COM DLL中的C ++调用函数可能发生内存泄漏

时间:2019-04-17 08:49:31

标签: c++ visual-c++ memory-leaks com

我使用VC ++ 2017创建了一个C ++控制台应用程序。随着时间的推移,它进行了多次调用以从第三方COM DLL中检索数据。我使用COM类(例如CComSafeArray和CComVariant)来管理自己的释放。

随着时间的推移,我发现在每次COM调用之后,任务管理器中我的App的内存都稳定增加。

我已经使用CRT库(https://docs.microsoft.com/en-us/visualstudio/debugger/finding-memory-leaks-using-the-crt-library?view=vs-2019)来检测内存泄漏,但这表明我没有泄漏。

我的问题是:

  1. COM通常是CRT自己做的内存管理 库无法检测到但与我的进程绑定?
  2. 如果是#1,是否有可用的工具来检测COM内存 泄漏?
  3. 如果是#1,有没有办法垃圾收集COM内存?

感谢您的考虑。

编辑4-19-2019 我发现COM Dll对于函数调用结果返回VARIANT和BSTR。我将它们分别分配给_variant_t和_bstr_t,以提供自动清理(理论上)。 例如。

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

DLL不使用CoTaskMemAlloc,但是使用SysAllocString生成BSTR。

2 个答案:

答案 0 :(得分:1)

COM不使用任何自动垃圾回收;尽管有可用的帮助程序类负责引用计数,但所有事情都必须考虑在内。

COM中的约定是,如果被调用的方法分配了一些内存,则调用者必须使用CoTaskMemFree释放它。您可能需要检查代码中是否有调用的DLL方法,如果它们在DLL分配的缓冲区中返回了任何内容,则需要通过调用CoTaskMemFree释放该缓冲区。

请参见https://docs.microsoft.com/en-us/windows/desktop/learnwin32/memory-allocation-in-com

此处有更多详细信息:https://docs.microsoft.com/en-us/windows/desktop/com/memory-management-rules

答案 1 :(得分:0)

_bstr_t b = GetSomeString();

大概是BSTR GetSomeString();。对于编译器意味着wchar_t* GetSomeStringBSTR告诉您它使用COM语义,但是编译器不知道。这些语义就是您称为SysFreeString

_bstr_t::_bstr_t( wchar_t* str ) 副本 str。是的,_bstr_t::~_bstr_t随后将调用SysFreeString,但它会在副本上调用。您需要在SysFreeString上致电BSTR GetSomeString();

解决方案是_bstr_t::_bstr_t( BSTR bstr , bool fCopy )fCopy=false。每个MSDN:

  

类型库中的包装函数使用此构造函数   标头,以封装并获取返回的BSTR的所有权   通过接口方法。

对于VARIANT,请参见_variant_t::_variant_t(VARIANT& varSrc, bool fCopy);。相同的想法。