我使用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)来检测内存泄漏,但这表明我没有泄漏。
我的问题是:
感谢您的考虑。
编辑4-19-2019 我发现COM Dll对于函数调用结果返回VARIANT和BSTR。我将它们分别分配给_variant_t和_bstr_t,以提供自动清理(理论上)。 例如。
_variant_t v = GetSomeVariant();
_bstr_t b = GetSomeString();
DLL不使用CoTaskMemAlloc,但是使用SysAllocString生成BSTR。
答案 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* GetSomeString
; BSTR
告诉您它使用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);
。相同的想法。