CComPtr的内存泄漏

时间:2019-05-03 02:50:43

标签: c++ memory-leaks visual-leak-detector

我使用crtdbg检测泄漏位置,并且在调用new时遇到了内存泄漏

CComPtr<IDBColumnInfo> m_spColumnInfo
CComPtr<CDBColumnInfo> spResult = new CDBColumnInfo(); //Memory leak here
//another logic come here to set data to spResult
//another logic come here to set data to spResult
//another logic come here to set data to spResult
m_spColumnInfo = static_cast<IDBColumnInfo*>(spResult.Detach());
spResult.Release();

spResult是否需要执行任何步骤?

1 个答案:

答案 0 :(得分:1)

内存泄漏,因为您没有正确管理CDBColumnInfo对象的引用计数。

初始化spResult时,对象的refcount初始化为1。调用spResult.Detach()时,对象的refcount仍为1,因为Detach()不会递减。然后,将分离的指针分配给m_spColumnInfo时,对象的refcount递增为2。稍后释放m_spColumnInfo时,它将对象的recount递减为1,并且对象泄漏。

您根本不应该分离spResult。将其原样分配给m_spColumnInfo,这会将refcount增加到2,然后让spResult正常超出范围,将refcount减小到1,使m_spColumnInfo处于唯一活动状态参考。然后稍后释放m_spColumnInfo时,引用计数将减少为0,并且对象将被释放。

您根本不应该尝试手动管理引用计数。这违反了使用CComPtr的全部目的。

CComPtr<IDBColumnInfo> m_spColumnInfo;

...

{
    CComPtr<CDBColumnInfo> spResult = new CDBColumnInfo();
    //set data to spResult
    m_spColumnInfo = spResult;
}

另外,请注意,您的函数根本没有业务调用CoInitialize()CoUninitialize()!您需要从函数中删除这些调用(特别是因为在退出函数的大多数代码路径中,函数甚至都没有调用CoUninitialize())。这些调用不是您的职能部门的责任。线程负责调用您的函数来决定其如何自行初始化COM。这些COM函数在每个线程中只能被调用一次,而不能在每个用户函数中被调用。