我有一个内存泄漏,我将其缩小为以下代码。这是怎么回事?
CComSafeArray<BSTR> sa(5);
sa[0] = SysAllocString("constant");
CComSafeArray::~CComSafeArray
调用SafeArrayDestroy
(通过CComSafeArray::Destroy()
,请参见下文),所有成员均使用should then call SysFreeString
。因此,这里不应该泄漏。这是怎么回事?HRESULT Destroy()
{
HRESULT hRes = S_OK;
if (m_psa != NULL)
{
hRes = Unlock();
if (SUCCEEDED(hRes))
{
hRes = SafeArrayDestroy(m_psa);
if (SUCCEEDED(hRes))
m_psa = NULL;
}
}
return hRes;
}
最佳答案
简短答案:CComSafeArray<BSTR>
和CComSafeArray<BSTR>::operator[]
而不是将指针的副本保存在CComSafeArray<BSTR>::GetAt(T)
中,而是返回一个CComBSTR
对象,该对象将获取BSTR
的副本。这导致BSTR
泄漏。
长答案:
经过几个小时没有结果的尝试后,尝试编译一个更简单的版本以缩小泄漏范围时出现了一个编译错误:
CComSafeArray<BSTR> sa(5);
sa[0] = nullptr;
这不会编译,因为
CComSafeArray<BSTR>::operator[]
在后台隐藏返回CComBSTR
对象,并且nullptr
可以匹配CComBSTR::operator=(LPCSTR)
和CComBSTR::operator=(LPCOLESTR)
。 Bam,编译错误。一旦我发现
CComBSTR
被掩盖,它就就位了。 CComBSTR::operator=
takes a copy of the BSTR
instead of saving the pointer(在正常行为下,我如何阅读代码)或拥有所有权,导致未释放的临时BSTR
泄漏。typename _ATL_AutomationType<T>::_typewrapper& GetAt(_In_ LONG lIndex) { ... }
...
// specialization for BSTR so GetT doesn't return &BSTR
template <>
struct _ATL_AutomationType<BSTR>
{
typedef CComBSTR _typewrapper ;
enum { type = VT_BSTR };
static void* GetT(_In_ const BSTR& t) throw()
{
return t;
}
};
关于c++ - 为什么在使用CComSafeArray <BSTR>时会泄漏内存?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/31584738/