【问题标题】:C++ Calling Functions in a COM DLL Possible Memory LeakCOM DLL 中的 C++ 调用函数可能存在内存泄漏
【发布时间】:2019-09-07 11:07:21
【问题描述】:

我使用 VC++ 2017 创建了一个 C++ 控制台应用程序。随着时间的推移,它会进行多次调用以从第 3 方 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 内存进行垃圾收集?

感谢您的考虑。

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

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

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

【问题讨论】:

  • 通过任务管理器观察内存增加并不是判断内存增加的可靠方法。当您delete/delete[]/free/etc 内存时,通常它不会直接返回操作系统。它保留供以后使用。
  • 考虑查看this question中的答案
  • 好吧,如果这是一个现代应用程序,那么 COM 对象的大量泄漏就不足为奇了,因为 MS 大多通过以前在 COM 中使用的引用计数放弃了对象生命周期管理的弱概念。因此,与其跟踪 COM 内存泄漏,不如专注于让应用在因资源耗尽而被终止后正确重启。
  • @VTT:如果我可以对 cme​​ts 投反对票,我会投反对票。

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


【解决方案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

【讨论】:

  • 我修改了我的问题(编辑注明),以提供一些关于 COM dll 返回什么以及我如何分配返回值的见解。
【解决方案2】:

_bstr_t b = GetSomeString();

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

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

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

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

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

【讨论】:

  • 我愿意接受这个答案,因为它是有道理的。但是,我发现这个 COM dll 泄漏了严重的内存,而我没有从中提取任何数据。它打开和关闭文件系统文件,但似乎不会自行清理。所以我不能肯定地说这个答案可以解决我的问题。不过,我确实采纳了这些建议。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-02-14
  • 1970-01-01
  • 2011-07-18
  • 1970-01-01
  • 2013-06-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多