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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C ++调用COM DLL中的函数可能发生内存泄漏相关的知识,希望对你有一定的参考价值。

我使用VC ++ 2017创建了一个C ++控制台应用程序。随着时间的推移,它会从第三方COM DLL中检索数据。我使用像CComSafeArray和CComVariant这样的COM类来管理自己的释放。

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

我已经使用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。

答案

_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);。同样的想法。

另一答案

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

以上是关于C ++调用COM DLL中的函数可能发生内存泄漏的主要内容,如果未能解决你的问题,请参考以下文章

matlab和C中的内存管理器问题[重复]

堆中的 DLL 内存泄漏

C++/C# 应用程序中的内存泄漏

DLL 中 C 样式函数中的静态变量

C++调用C#dll类库中的方法(非显性COM)

Python C 包装器内存泄漏