C++ CComPtr内存泄漏

C++ CComPtr内存泄漏,c++,memory-leaks,visual-leak-detector,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 //a

我使用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();
CComPtr m\u spColumnInfo
CComPtr spResult=新的CDBColumnInfo()//内存泄漏
//另一个逻辑用于将数据设置为spResult
//另一个逻辑用于将数据设置为spResult
//另一个逻辑用于将数据设置为spResult
m_spColumnInfo=静态_转换(spResult.Detach());
spResult.Release();

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

您存在内存泄漏,因为您对
CDBColumnInfo
对象的引用计数管理不当

初始化
spResult
时,对象的refcount被初始化为1。调用
spResult.Detach()
时,对象的refcount仍然为1,因为
Detach()
不会将其递减。然后将分离的指针指定给
m_spColumnInfo
时,对象的refcount将增加到2。当稍后发布
m_spColumnInfo
时,它将对象的重新计数减为1,并且对象泄漏

您根本不应该分离
spResult
。按原样将其分配给
m_spColumnInfo
,这将使refcount增加到2,然后让
spResult
正常超出范围,将refcount减少到1,使
m_spColumnInfo
只保留活动引用。稍后释放
m_spColumnInfo
时,refcount将递减为0,对象将被释放

您根本不应该尝试手动管理refcount。这违背了使用
CComPtr
的全部目的

CComPtr<IDBColumnInfo> m_spColumnInfo;

...

{
    CComPtr<CDBColumnInfo> spResult = new CDBColumnInfo();
    //set data to spResult
    m_spColumnInfo = spResult;
}
CComPtr m_spColumnInfo;
...
{
CComPtr spResult=新的CDBColumnInfo();
//将数据设置为spResult
m_spColumnInfo=spResult;
}

另外,另一方面,您的函数根本不需要调用
CoInitialize()
CoUninitialize()
!您需要从函数中删除这些调用(特别是因为您的函数在退出函数的大多数代码路径中甚至不调用
coninitialize()
)。这些调用不是您的函数的责任。调用函数的线程负责决定如何为自己初始化COM。每个线程只能调用一次这些COM函数,而不是每个用户函数。

为什么需要
spResult.Detach()
?为什么不这样做:
m\u spColumnInfo=static\u cast(spResult)
?我有一段时间没有使用
CComPtr
,但是操作符说
操作符=
会增加引用计数,所以通过使用
Detach
,我认为当您尝试转移所有权时,您将得到一个额外的
AddRef
,而没有相应的
释放。尝试用我建议的行替换
spResult.Detach()
。@jamesdlin在查看实际代码后,我在该函数中遇到异常:您根本不需要
删除spResult
。另外,我会将
spResult
声明为
CComPtr
,然后完全摆脱
静态转换。@jamesdlin我改为
CComPtr spResult=new-cdbcolumnfo()
但是具有一些功能的
CDBColumnInfo
无法通过
spResult
访问。Ex
HRESULT CDBColumnInfo::GetField(LPCOLESTR fieldName)