我有一个内存泄漏,我将其缩小为以下代码。这是怎么回事?

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/

10-10 21:24