C++ 在 COM DLL 中调用函数可能的内存泄漏
C++ Calling Functions in a COM DLL Possible Memory Leak
我使用 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) 尝试检测内存泄漏,但它表明我有 none。
我的问题is/are:
- COM 是否通常进行 CRT 自己的内存管理
库无法检测到但与我的进程相关联?
- 如果#1 是这种情况,是否有可用的工具来检测 COM 内存
泄漏?
- 如果#1 是这种情况,是否有垃圾收集 COM 内存的方法?
感谢您的考虑。
编辑 2019 年 4 月 19 日
我发现函数调用结果的 COM Dll returns VARIANT 和 BSTR。我将它们分配给 _variant_t 和 _bstr_t 以提供自动清理(理论上)。
例如。
_variant_t v = GetSomeVariant();
_bstr_t b = GetSomeString();
DLL 不使用 CoTaskMemAlloc,但它确实使用 SysAllocString 来生成 BSTR。
COM 不使用任何自动垃圾收集;尽管有帮助程序 类 可用于处理引用计数,但所有内容都必须考虑在内。
COM 中的惯例是,如果被调用的方法分配了一些内存,那么调用者必须使用 CoTaskMemFree
释放它。您可能想检查您调用的 DLL 方法的代码,如果它们 return 由 DLL 分配的缓冲区中的任何内容,那么您需要通过调用 CoTaskMemFree
.[ 来释放该缓冲区。 =14=]
见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
_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
,但它是在副本上调用的。您需要在 BSTR GetSomeString();
上调用 SysFreeString
。
解决方案是 _bstr_t::_bstr_t( BSTR bstr , bool fCopy )
和 fCopy=false
。根据 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.
对于 VARIANT
,参见 _variant_t::_variant_t(VARIANT& varSrc, bool fCopy);
。同样的想法。
我使用 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) 尝试检测内存泄漏,但它表明我有 none。
我的问题is/are:
- COM 是否通常进行 CRT 自己的内存管理 库无法检测到但与我的进程相关联?
- 如果#1 是这种情况,是否有可用的工具来检测 COM 内存 泄漏?
- 如果#1 是这种情况,是否有垃圾收集 COM 内存的方法?
感谢您的考虑。
编辑 2019 年 4 月 19 日 我发现函数调用结果的 COM Dll returns VARIANT 和 BSTR。我将它们分配给 _variant_t 和 _bstr_t 以提供自动清理(理论上)。 例如。
_variant_t v = GetSomeVariant();
_bstr_t b = GetSomeString();
DLL 不使用 CoTaskMemAlloc,但它确实使用 SysAllocString 来生成 BSTR。
COM 不使用任何自动垃圾收集;尽管有帮助程序 类 可用于处理引用计数,但所有内容都必须考虑在内。
COM 中的惯例是,如果被调用的方法分配了一些内存,那么调用者必须使用 CoTaskMemFree
释放它。您可能想检查您调用的 DLL 方法的代码,如果它们 return 由 DLL 分配的缓冲区中的任何内容,那么您需要通过调用 CoTaskMemFree
.[ 来释放该缓冲区。 =14=]
见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
_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
,但它是在副本上调用的。您需要在 BSTR GetSomeString();
上调用 SysFreeString
。
解决方案是 _bstr_t::_bstr_t( BSTR bstr , bool fCopy )
和 fCopy=false
。根据 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.
对于 VARIANT
,参见 _variant_t::_variant_t(VARIANT& varSrc, bool fCopy);
。同样的想法。